diff --git a/docs/images/ili9341.jpg b/docs/images/ili9341.jpg new file mode 100644 index 00000000..04e2810f Binary files /dev/null and b/docs/images/ili9341.jpg differ diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 3fbfad22..d1f3b1cd 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -226,6 +226,7 @@ add_example (mcp9808) add_example (groveultrasonic) add_example (sx1276-lora) add_example (sx1276-fsk) +add_example (ili9341) if (OPENZWAVE_FOUND) include_directories(${OPENZWAVE_INCLUDE_DIRS}) add_example (ozw) diff --git a/examples/c++/ili9341.cxx b/examples/c++/ili9341.cxx new file mode 100644 index 00000000..8fe397a9 --- /dev/null +++ b/examples/c++/ili9341.cxx @@ -0,0 +1,84 @@ +/** + * Author: Shawn Hymel + * Copyright (c) 2016 SparkFun Electronics + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include "ili9341.h" + +int main(int argc, char **argv) { +//! [Interesting] + + // Pins (Edison) + // CS_LCD GP44 (MRAA 31) + // CS_SD GP43 (MRAA 38) unused + // DC GP12 (MRAA 20) + // RESEST GP13 (MRAA 14) + upm::ILI9341 * lcd = new upm::ILI9341(31, 38, 20, 14); + + // Fill the screen with a solid color + lcd->fillScreen(lcd->color565(0, 40, 16)); + + // Draw some shapes + lcd->drawFastVLine(10, 10, 100, ILI9341_RED); + lcd->drawFastHLine(20, 10, 50, ILI9341_CYAN); + lcd->drawLine(160, 30, 200, 60, ILI9341_GREEN); + lcd->fillRect(20, 30, 75, 60, ILI9341_ORANGE); + lcd->drawCircle(70, 50, 20, ILI9341_PURPLE); + lcd->fillCircle(120, 50, 20, ILI9341_PURPLE); + lcd->drawTriangle(50, 100, 10, 140, 90, 140, ILI9341_YELLOW); + lcd->fillTriangle(150, 100, 110, 140, 190, 140, ILI9341_YELLOW); + lcd->drawRoundRect(20, 150, 50, 30, 10, ILI9341_RED); + lcd->drawRoundRect(130, 150, 50, 30, 10, ILI9341_RED); + lcd->fillRoundRect(75, 150, 50, 30, 10, ILI9341_RED); + + // Write some text + lcd->setCursor(0, 200); + lcd->setTextColor(ILI9341_LIGHTGREY); + lcd->setTextWrap(true); + lcd->setTextSize(1); + lcd->print("Text 1\n"); + lcd->setTextSize(2); + lcd->print("Text 2\n"); + lcd->setTextSize(3); + lcd->print("Text 3\n"); + lcd->setTextSize(4); + lcd->print("Text 4\n"); + + // Test screen rotation + for(int r = 0; r < 4; r++) { + lcd->setRotation(r); + lcd->fillRect(0, 0, 5, 5, ILI9341_WHITE); + sleep(1); + } + + // Invert colors, wait, then revert back + lcd->invertDisplay(true); + sleep(2); + lcd->invertDisplay(false); + + // Don't forget to free up that memory! + delete lcd; +//! [Interesting] + return 0; +} \ No newline at end of file diff --git a/examples/javascript/ili9341.js b/examples/javascript/ili9341.js new file mode 100644 index 00000000..ba0f47b5 --- /dev/null +++ b/examples/javascript/ili9341.js @@ -0,0 +1,79 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/** + * Author: Shawn Hymel + * Copyright (c) 2016 SparkFun Electronics + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +var ili9341 = require('jsupm_ili9341'); + +// Pins (Edison) +// CS_LCD GP44 (MRAA 31) +// CS_SD GP43 (MRAA 38) unused +// DC GP12 (MRAA 20) +// RESEST GP13 (MRAA 14) +var lcd = new ili9341.ILI9341(31, 38, 20, 14); + +// Fill the screen with a solid color +lcd.fillScreen(lcd.color565(0, 40, 16)); + +// Draw some shapes +lcd.drawFastVLine(10, 10, 100, ili9341.ILI9341_RED); +lcd.drawFastHLine(20, 10, 50, ili9341.ILI9341_CYAN); +lcd.drawLine(160, 30, 200, 60, ili9341.ILI9341_GREEN); +lcd.fillRect(20, 30, 75, 60, ili9341.ILI9341_ORANGE); +lcd.drawCircle(70, 50, 20, ili9341.ILI9341_PURPLE); +lcd.fillCircle(120, 50, 20, ili9341.ILI9341_PURPLE); +lcd.drawTriangle(50, 100, 10, 140, 90, 140, ili9341.ILI9341_YELLOW); +lcd.fillTriangle(150, 100, 110, 140, 190, 140, ili9341.ILI9341_YELLOW); +lcd.drawRoundRect(20, 150, 50, 30, 10, ili9341.ILI9341_RED); +lcd.drawRoundRect(130, 150, 50, 30, 10, ili9341.ILI9341_RED); +lcd.fillRoundRect(75, 150, 50, 30, 10, ili9341.ILI9341_RED); + +// Write some text +lcd.setCursor(0, 200); +lcd.setTextColor(ili9341.ILI9341_LIGHTGREY); +lcd.setTextWrap(true); +lcd.setTextSize(1); +lcd.print("Text 1\n"); +lcd.setTextSize(2); +lcd.print("Text 2\n"); +lcd.setTextSize(3); +lcd.print("Text 3\n"); +lcd.setTextSize(4); +lcd.print("Text 4\n"); + +// Test screen rotation +function rotateScreen(r) { + lcd.setRotation(r); + lcd.fillRect(0, 0, 5, 5, ili9341.ILI9341_WHITE); + if (r < 4) { + r++; + setTimeout(function() { rotateScreen(r); }, 1000); + } +} +rotateScreen(0); + +// Invert colors, wait, then revert back +setTimeout(function() { lcd.invertDisplay(true); }, 4000); +setTimeout(function() { lcd.invertDisplay(false); }, 6000); \ No newline at end of file diff --git a/examples/python/ili9341.py b/examples/python/ili9341.py new file mode 100644 index 00000000..5194cc31 --- /dev/null +++ b/examples/python/ili9341.py @@ -0,0 +1,75 @@ +#!/usr/bin/python +# Author: Shawn Hymel +# Copyright (c) 2016 SparkFun Electronics +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import time +import pyupm_ili9341 as ili9341 + +# Pins (Edison) +# CS_LCD GP44 (MRAA 31) +# CS_SD GP43 (MRAA 38) unused +# DC GP12 (MRAA 20) +# RESEST GP13 (MRAA 14) +lcd = ili9341.ILI9341(31, 38, 20, 14) + +# Fill the screen with a solid color +lcd.fillScreen(lcd.color565(0, 40, 16)) + +# Draw some shapes +lcd.drawFastVLine(10, 10, 100, ili9341.ILI9341_RED) +lcd.drawFastHLine(20, 10, 50, ili9341.ILI9341_CYAN) +lcd.drawLine(160, 30, 200, 60, ili9341.ILI9341_GREEN) +lcd.fillRect(20, 30, 75, 60, ili9341.ILI9341_ORANGE) +lcd.drawCircle(70, 50, 20, ili9341.ILI9341_PURPLE) +lcd.fillCircle(120, 50, 20, ili9341.ILI9341_PURPLE) +lcd.drawTriangle(50, 100, 10, 140, 90, 140, ili9341.ILI9341_YELLOW) +lcd.fillTriangle(150, 100, 110, 140, 190, 140, ili9341.ILI9341_YELLOW) +lcd.drawRoundRect(20, 150, 50, 30, 10, ili9341.ILI9341_RED) +lcd.drawRoundRect(130, 150, 50, 30, 10, ili9341.ILI9341_RED) +lcd.fillRoundRect(75, 150, 50, 30, 10, ili9341.ILI9341_RED) + +# Write some text +lcd.setCursor(0, 200) +lcd.setTextColor(ili9341.ILI9341_LIGHTGREY) +lcd.setTextWrap(True) +lcd.setTextSize(1) +lcd._print("Text 1\n") +lcd.setTextSize(2) +lcd._print("Text 2\n") +lcd.setTextSize(3) +lcd._print("Text 3\n") +lcd.setTextSize(4) +lcd._print("Text 4\n") + +# Test screen rotation +for r in range(0, 4): + lcd.setRotation(r) + lcd.fillRect(0, 0, 5, 5, ili9341.ILI9341_WHITE) + time.sleep(1) + +# Invert colors, wait, then revert back +lcd.invertDisplay(True) +time.sleep(2) +lcd.invertDisplay(False) + +# Don't forget to free up that memory! +del lcd \ No newline at end of file diff --git a/src/ili9341/CMakeLists.txt b/src/ili9341/CMakeLists.txt new file mode 100644 index 00000000..6998826b --- /dev/null +++ b/src/ili9341/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "ili9341") +set (libdescription "libupm ILI9341 SPI LCD") +set (module_src gfx.cxx ili9341.cxx) +set (module_h gfx.h ili9341.h) +upm_module_init() diff --git a/src/ili9341/gfx.cxx b/src/ili9341/gfx.cxx new file mode 100644 index 00000000..90f83dec --- /dev/null +++ b/src/ili9341/gfx.cxx @@ -0,0 +1,749 @@ +/** + * Author: Shawn Hymel + * Copyright (c) 2016 SparkFun Electronics + * + * Based on GFX interface by Yevgeniy Kiveisha and Adafruit Industries. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "gfx.h" + +using namespace upm; + +GFX::GFX(int16_t w, int16_t h) : WIDTH(w), HEIGHT(h) { + _width = WIDTH; + _height = HEIGHT; + rotation = 0; + + cursor_x = 0; + cursor_y = 0; + textsize = 1; + textcolor = 0xFFFF; + textbgcolor = 0xFFFF; + wrap = true; + _cp437 = false; +} + +void GFX::drawLine(int16_t x0, + int16_t y0, + int16_t x1, + int16_t y1, + uint16_t color) { + + int16_t steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { + adagfxswap(x0, y0); + adagfxswap(x1, y1); + } + + if (x0 > x1) { + adagfxswap(x0, x1); + adagfxswap(y0, y1); + } + + int16_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int16_t err = dx / 2; + int16_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1; + } + + for (; x0<=x1; x0++) { + if (steep) { + drawPixel(y0, x0, color); + } else { + drawPixel(x0, y0, color); + } + err -= dy; + if (err < 0) { + y0 += ystep; + err += dx; + } + } +} + +void GFX::drawFastVLine(int16_t x, + int16_t y, + int16_t h, + uint16_t color) { + drawLine(x, y, x, y+h-1, color); +} + +void GFX::drawFastHLine(int16_t x, + int16_t y, + int16_t w, + uint16_t color) { + drawLine(x, y, x+w-1, y, color); +} + +void GFX::drawRect(int16_t x, + int16_t y, + int16_t w, + int16_t h, + uint16_t color) { + drawFastHLine(x, y, w, color); + drawFastHLine(x, y+h-1, w, color); + drawFastVLine(x, y, h, color); + drawFastVLine(x+w-1, y, h, color); +} + +void GFX::fillRect(int16_t x, + int16_t y, + int16_t w, + int16_t h, + uint16_t color) { + for (int16_t i=x; i= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + drawPixel(x0 + x, y0 + y, color); + drawPixel(x0 - x, y0 + y, color); + drawPixel(x0 + x, y0 - y, color); + drawPixel(x0 - x, y0 - y, color); + drawPixel(x0 + y, y0 + x, color); + drawPixel(x0 - y, y0 + x, color); + drawPixel(x0 + y, y0 - x, color); + drawPixel(x0 - y, y0 - x, color); + } +} + +void GFX::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= 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 GFX::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); +} + +void GFX::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= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x1) { + drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); + drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); + } + if (cornername & 0x2) { + drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); + drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); + } + } +} + +void GFX::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); +} + +void GFX::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) { + adagfxswap(y0, y1); adagfxswap(x0, x1); + } + if (y1 > y2) { + adagfxswap(y2, y1); adagfxswap(x2, x1); + } + if (y0 > y1) { + adagfxswap(y0, y1); adagfxswap(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; + int32_t + 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) adagfxswap(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) adagfxswap(a,b); + drawFastHLine(a, y, b-a+1, color); + } +} + +// Draw a rounded rectangle +void GFX::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-2*r, color); // Top + drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom + drawFastVLine(x , y+r , h-2*r, color); // Left + drawFastVLine(x+w-1, y+r , h-2*r, 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); +} + +void GFX::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-2*r-1, color); + fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); +} + +void GFX::drawChar(int16_t x, + int16_t y, + unsigned char c, + uint16_t color, + uint16_t bg, + uint8_t size) { + + if((x >= _width) || // Clip right + (y >= _height) || // Clip bottom + ((x + 6 * size - 1) < 0) || // Clip left + ((y + 8 * size - 1) < 0)) // Clip top + return; + + if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior + + for(int8_t i=0; i<6; i++ ) { + uint8_t line; + if(i < 5) line = font[(c * 5) + i]; + else line = 0x0; + for(int8_t j=0; j<8; j++, line >>= 1) { + if(line & 0x1) { + if(size == 1) drawPixel(x+i, y+j, color); + else fillRect(x+(i*size), y+(j*size), size, size, color); + } else if(bg != color) { + if(size == 1) drawPixel(x+i, y+j, bg); + else fillRect(x+i*size, y+j*size, size, size, bg); + } + } + } +} + +int16_t GFX::getCursorX(void) const { + return cursor_x; +} + +int16_t GFX::getCursorY(void) const { + return cursor_y; +} + +void GFX::setCursor(int16_t x, int16_t y) { + cursor_x = x; + cursor_y = y; +} + +void GFX::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 GFX::setTextColor(uint16_t c, uint16_t bg) { + textcolor = c; + textbgcolor = bg; +} + +void GFX::setTextSize(uint8_t s) { + textsize = (s > 0) ? s : 1; +} + +void GFX::setTextWrap(bool w) { + wrap = w; +} + +uint8_t GFX::getRotation(void) const { + return rotation; +} + +void GFX::setRotation(uint8_t r) { + rotation = (r & 3); + switch(rotation) { + case 0: + case 2: + _width = WIDTH; + _height = HEIGHT; + break; + case 1: + case 3: + _width = HEIGHT; + _height = WIDTH; + break; + } +} + +void GFX::cp437(bool x) { + _cp437 = x; +} + +void GFX::write(uint8_t c) { + + if(c == '\n') { + cursor_y += textsize*8; + cursor_x = 0; + } else if(c == '\r') { + // skip em + } else { + + // Heading off edge? + if(wrap && ((cursor_x + textsize * 6) >= _width)) { + cursor_x = 0; // Reset x to zero + cursor_y += textsize * 8; // Advance y one line + } + drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + cursor_x += textsize * 6; + } +} + +void GFX::print(std::string msg) { + int len = msg.length(); + for (int idx = 0; idx < len; idx++) { + write(msg[idx]); + } +} + +int16_t GFX::width(void) const { + return _width; +} + +int16_t GFX::height(void) const { + return _height; +} + +const unsigned char GFX::font[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08, + 0x10, 0x20, 0x7E, 0x20, 0x10, + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22, + 0x7F, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x49, 0x49, 0x49, 0x41, + 0x7F, 0x09, 0x09, 0x09, 0x01, + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code + 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block + 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x08, 0x08, 0x6B, 0x6B, 0x08, + 0x36, 0x12, 0x36, 0x24, 0x36, + 0x06, 0x0F, 0x09, 0x0F, 0x06, + 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, + 0x30, 0x40, 0xFF, 0x01, 0x01, + 0x00, 0x1F, 0x01, 0x01, 0x1E, + 0x00, 0x19, 0x1D, 0x17, 0x12, + 0x00, 0x3C, 0x3C, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP +}; \ No newline at end of file diff --git a/src/ili9341/gfx.h b/src/ili9341/gfx.h new file mode 100644 index 00000000..3cbc5a12 --- /dev/null +++ b/src/ili9341/gfx.h @@ -0,0 +1,407 @@ +/** + * Author: Shawn Hymel + * Copyright (c) 2016 SparkFun Electronics + * + * Based on GFX interface by Yevgeniy Kiveisha and Adafruit Industries. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include + +#define adagfxswap(a, b) { int16_t t = a; a = b; b = t; } + +namespace upm +{ + + /** + * @brief GFX helper class + */ + class GFX { + public: + + /** + * Creates a GFX object + * + * @param w Screen width + * @param h Screen height + */ + GFX(int16_t w, int16_t h); + + /** + * Sends a pixel color (RGB) to the driver chip. This must be + * defined by the subclass (pure virtual function). + * + * @param x Axis on the horizontal scale + * @param y Axis on the vertical scale + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; + + /** + * Draw a line. + * + * @param x0 Start of line x coordinate + * @param y0 Start of line y coordinate + * @param x1 End of line x coordinate + * @param y1 End of line y coordinate + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + virtual void drawLine(int16_t x0, + int16_t y0, + int16_t x1, + int16_t y1, + uint16_t color); + + /** + * Draws a vertical line using minimal SPI writes. + * + * @param x Axis on the horizontal scale to begin line + * @param y Axis on the vertical scale to begin line + * @param h Height of line in pixels + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + virtual void drawFastVLine(int16_t x, + int16_t y, + int16_t h, + uint16_t color); + + /** + * Draws a horizontal line using minimal SPI writes. + * + * @param x Axis on the horizontal scale to begin line + * @param y Axis on the vertical scale to begin line + * @param w Width of line in pixels + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + virtual void drawFastHLine(int16_t x, + int16_t y, + int16_t w, + uint16_t color); + + /** + * Draws a rectangle (not filled). + * + * @param x Position of upper left corner on horizontal axis + * @param y Position of upper left corner on vertical axis + * @param w Width of rectangle + * @param h Height of rectangle + * @color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + virtual void drawRect(int16_t x, + int16_t y, + int16_t w, + int16_t h, + uint16_t color); + + /** + * Draw a filled rectangle. + * + * @param x Axis on the horizontal scale of upper-left corner + * @param y Axis on the vertical scale of upper-left corner + * @param w Width of rectangle in pixels + * @param h Height of rectangle in pixels + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + virtual void fillRect(int16_t x, + int16_t y, + int16_t w, + int16_t h, + uint16_t color); + + /** + * Fill the screen with a single color. + * + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + virtual void fillScreen(uint16_t color); + + /** + * Invert colors on the display. + * + * @param i True or false to invert colors + */ + virtual void invertDisplay(bool i); + + /** + * Draw a circle outline. + * + * @param x0 Center point of circle on x-axis + * @param y0 Center point of circle on y-axis + * @param r Radius of circle + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color); + + /** + * Used to draw rounded corners. + * + * @param x0 Center point of circle on x-axis + * @param y0 Center point of circle on y-axis + * @param r Radius of circle + * @param cornername Mask of corner number (1, 2, 4, 8) + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void drawCircleHelper(int16_t x0, + int16_t y0, + int16_t r, + uint8_t cornername, + uint16_t color); + + /** + * Draws a filled circle. + * + * @param x0 Center point of circle on x-axis + * @param y0 Center point of circle on y-axis + * @param r Radius of circle + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color); + + /** + * Used to draw a filled circle and rounded rectangles. + * + * @param x0 Center point of circle on x-axis + * @param y0 Center point of circle on y-axis + * @param r Radius of circle + * @param cornername Mask of corner number (1, 2, 4, 8) + * @param delta Line offset + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void fillCircleHelper(int16_t x0, + int16_t y0, + int16_t r, + uint8_t cornername, + int16_t delta, + uint16_t color); + + /** + * Draw a triangle. + * + * @param x0 First point coordinate on x-axis + * @param y0 First point coordinate on y-axis + * @param x1 Second point coordinate on x-axis + * @param y1 Second point coordinate on y-axis + * @param x2 Third point coordinate on x-axis + * @param y2 Third point coordinate on y-axis + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void drawTriangle(int16_t x0, + int16_t y0, + int16_t x1, + int16_t y1, + int16_t x2, + int16_t y2, + uint16_t color); + + /** + * Draw a filled triangle. + * + * @param x0 First point coordinate on x-axis + * @param y0 First point coordinate on y-axis + * @param x1 Second point coordinate on x-axis + * @param y1 Second point coordinate on y-axis + * @param x2 Third point coordinate on x-axis + * @param y2 Third point coordinate on y-axis + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void fillTriangle(int16_t x0, + int16_t y0, + int16_t x1, + int16_t y1, + int16_t x2, + int16_t y2, + uint16_t color); + + /** + * Draw a rectangle with rounded corners + * + * @param x0 X-axis coordinate of top-left corner + * @param y0 Y-axis coordinate of top-left corner + * @param w Width of rectangle + * @param h height of rectangle + * @param radius Radius of rounded corners + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void drawRoundRect(int16_t x0, + int16_t y0, + int16_t w, + int16_t h, + int16_t radius, + uint16_t color); + + /** + * Draw a filled rectangle with rounded corners + * + * @param x0 X-axis coordinate of top-left corner + * @param y0 Y-axis coordinate of top-left corner + * @param w Width of rectangle + * @param h height of rectangle + * @param radius Radius of rounded corners + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void fillRoundRect(int16_t x0, + int16_t y0, + int16_t w, + int16_t h, + int16_t radius, + uint16_t color); + + /** + * Draw a character at the specified point. + * + * @param x X-axis coordinate of the top-left corner + * @param y Y-axis coordinate of the top-left corner + * @param c Character to draw + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + * @param bg Background color (16-bit RGB) + * @param size Font size + */ + void drawChar(int16_t x, + int16_t y, + unsigned char c, + uint16_t color, + uint16_t bg, + uint8_t size); + + /** + * Get the x-axis coordinate of the upper-left corner of the cursor. + * + * @return X-axis coordinate of the cursor + */ + int16_t getCursorX(void) const; + + /** + * Get the y-axis coordinate of the upper-left corner of the cursor. + * + * @return Y-axis coordinate of the cursor + */ + int16_t getCursorY(void) const; + + /** + * Set the cursor for writing text. + * + * @param x X-axis coordinate of the top-left corner of the cursor + * @param y Y-axis coordinate of the top-left corner of the cursor + */ + void setCursor(int16_t x, int16_t y); + + /** + * Set the color for text. + * + * @param c RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void setTextColor(uint16_t c); + + /** + * Set the color for text and text background (highlight). + * + * @param c Text color (RGB, 16-bit) + * @param bg Background text color (RGB, 16-bit) + */ + void setTextColor(uint16_t c, uint16_t bg); + + /** + * Set the size of the text. + * + * @param s Font size (multiples of 8 pixel text height) + */ + void setTextSize(uint8_t s); + + /** + * Enable or disable text wrapping. + * + * @param w True to wrap text. False to truncate. + */ + void setTextWrap(bool w); + + /** + * Get the current rotation configuration of the screen. + * + * @return current rotation 0-3 + */ + uint8_t getRotation(void) const; + + /** + * Sets the rotation of the screen. Can be overridden with another + * screen-specific definition. + * + * @param r Rotation 0-3 + */ + void setRotation(uint8_t r); + + /** + * Enable (or disable) Code Page 437-compatible charset. + * + * @param x True to enable CP437 charset. False to disable. + */ + void cp437(bool x); + + /** + * Write a character at the current cursor position. Definition + * can be overridden with board-specific code. + * + * @param c Character to draw + */ + virtual void write(uint8_t c); + + /** + * Prints a string to the screen. + * + * @param s Message to print + */ + void print(std::string msg); + + /** + * Get the current width of the screen. + * + * @return the width in pixels + */ + int16_t width(void) const; + + /** + * Get the current height of the screen. + * + * @return the height in pixels + */ + int16_t height(void) const; + + protected: + + const int16_t WIDTH; + const int16_t HEIGHT; + + int16_t _width; + int16_t _height; + + uint8_t rotation; + + uint16_t textcolor; + uint16_t textbgcolor; + int16_t cursor_x; + int16_t cursor_y; + uint8_t textsize; + bool wrap; + bool _cp437; + static const unsigned char font[]; + }; +} \ No newline at end of file diff --git a/src/ili9341/ili9341.cxx b/src/ili9341/ili9341.cxx new file mode 100644 index 00000000..b0a4e577 --- /dev/null +++ b/src/ili9341/ili9341.cxx @@ -0,0 +1,487 @@ +/* + * Author: Shawn Hymel + * Copyright (c) 2015 SparkFun Electronics + * + * Credits to Adafruit. + * Based on Adafruit ST7735 library, see original license in license.txt file. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ili9341.h" + +using namespace upm; + +ILI9341::ILI9341(uint8_t csLCD, uint8_t csSD, uint8_t dc, uint8_t rst) : + GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT), m_csLCDPinCtx(csLCD), + m_csSDPinCtx(csSD), m_dcPinCtx(dc), m_rstPinCtx(rst), m_spi(0) { + + initModule(); + configModule(); +} + +void ILI9341::initModule() { + mraa::Result error = mraa::SUCCESS; + + error = m_csLCDPinCtx.dir(mraa::DIR_OUT); + if (error != mraa::SUCCESS) { + mraa::printError(error); + } + + error = m_csSDPinCtx.dir(mraa::DIR_OUT); + if (error != mraa::SUCCESS) { + mraa::printError(error); + } + + error = m_dcPinCtx.dir(mraa::DIR_OUT); + if (error != mraa::SUCCESS) { + mraa::printError(error); + } + + error = m_rstPinCtx.dir(mraa::DIR_OUT); + if (error != mraa::SUCCESS) { + mraa::printError(error); + } + + error = m_spi.frequency(SPI_FREQ); + if (error != mraa::SUCCESS) { + mraa::printError (error); + } + + lcdCSOff(); +} + +void ILI9341::setRotation(uint8_t r) { + + writecommand(ILI9341_MADCTL); + r = r % 4; // can't be higher than 3 + switch(r) { + case 0: + writedata(MADCTL_MX | MADCTL_BGR); + _width = ILI9341_TFTWIDTH; + _height = ILI9341_TFTHEIGHT; + break; + case 1: + writedata(MADCTL_MV | MADCTL_BGR); + _width = ILI9341_TFTHEIGHT; + _height = ILI9341_TFTWIDTH; + break; + case 2: + writedata(MADCTL_MY | MADCTL_BGR); + _width = ILI9341_TFTWIDTH; + _height = ILI9341_TFTHEIGHT; + break; + case 3: + writedata(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR); + _width = ILI9341_TFTHEIGHT; + _height = ILI9341_TFTWIDTH; + break; + } +} + +void ILI9341::configModule() { + + // Toggle RST low to reset + rstHigh(); + usleep(5000); + rstLow(); + usleep(20000); + rstHigh(); + usleep(150000); + + // Send initialization commands + writecommand(0xEF); + writedata(0x03); + writedata(0x80); + writedata(0x02); + + writecommand(0xCF); + writedata(0x00); + writedata(0XC1); + writedata(0X30); + + writecommand(0xED); + writedata(0x64); + writedata(0x03); + writedata(0X12); + writedata(0X81); + + writecommand(0xE8); + writedata(0x85); + writedata(0x00); + writedata(0x78); + + writecommand(0xCB); + writedata(0x39); + writedata(0x2C); + writedata(0x00); + writedata(0x34); + writedata(0x02); + + writecommand(0xF7); + writedata(0x20); + + writecommand(0xEA); + writedata(0x00); + writedata(0x00); + + writecommand(ILI9341_PWCTR1); //Power control + writedata(0x23); //VRH[5:0] + + writecommand(ILI9341_PWCTR2); //Power control + writedata(0x10); //SAP[2:0];BT[3:0] + + writecommand(ILI9341_VMCTR1); //VCM control + writedata(0x3e); + writedata(0x28); + + writecommand(ILI9341_VMCTR2); //VCM control2 + writedata(0x86); //-- + + writecommand(ILI9341_MADCTL); // Memory Access Control + writedata(0x48); + + writecommand(ILI9341_PIXFMT); + writedata(0x55); + + writecommand(ILI9341_FRMCTR1); + writedata(0x00); + writedata(0x18); + + writecommand(ILI9341_DFUNCTR); // Display Function Control + writedata(0x08); + writedata(0x82); + writedata(0x27); + + writecommand(0xF2); // 3Gamma Function Disable + writedata(0x00); + + writecommand(ILI9341_GAMMASET); //Gamma curve selected + writedata(0x01); + + writecommand(ILI9341_GMCTRP1); //Set Gamma + writedata(0x0F); + writedata(0x31); + writedata(0x2B); + writedata(0x0C); + writedata(0x0E); + writedata(0x08); + writedata(0x4E); + writedata(0xF1); + writedata(0x37); + writedata(0x07); + writedata(0x10); + writedata(0x03); + writedata(0x0E); + writedata(0x09); + writedata(0x00); + + writecommand(ILI9341_GMCTRN1); //Set Gamma + writedata(0x00); + writedata(0x0E); + writedata(0x14); + writedata(0x03); + writedata(0x11); + writedata(0x07); + writedata(0x31); + writedata(0xC1); + writedata(0x48); + writedata(0x08); + writedata(0x0F); + writedata(0x0C); + writedata(0x31); + writedata(0x36); + writedata(0x0F); + + writecommand(ILI9341_SLPOUT); + usleep(120000); + writecommand(ILI9341_DISPON); +} + +void ILI9341::setAddrWindow(uint16_t x0, + uint16_t y0, + uint16_t x1, + uint16_t y1) { + + writecommand(ILI9341_CASET); // Column addr set + writedata(x0 >> 8); + writedata(x0 & 0xFF); // XSTART + writedata(x1 >> 8); + writedata(x1 & 0xFF); // XEND + + writecommand(ILI9341_PASET); // Row addr set + writedata(y0>>8); + writedata(y0); // YSTART + writedata(y1>>8); + writedata(y1); // YEND + + writecommand(ILI9341_RAMWR); // write to RAM +} + +void ILI9341::drawPixel(int16_t x, int16_t y, uint16_t color) { + + if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) { + return; + } + + setAddrWindow(x, y, x + 1, y + 1); + + writedata(color >> 8); + writedata(color); +} + +void ILI9341::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { + + // Rudimentary clipping + if((x >= _width) || (y >= _height)) { + return; + } + + if((y+h-1) >= _height) { + h = _height-y; + } + + setAddrWindow(x, y, x, y+h-1); + + uint8_t hi = color >> 8; + uint8_t lo = color; + + lcdCSOn(); + dcHigh(); + + while (h--) { + m_spi.writeByte(hi); + m_spi.writeByte(lo); + } + + lcdCSOff(); +} + +void ILI9341::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { + + // Rudimentary clipping + if((x >= _width) || (y >= _height)) { + return; + } + + if((x+w-1) >= _width) { + w = _width - x; + } + + setAddrWindow(x, y, x+w-1, y); + + uint8_t hi = color >> 8; + uint8_t lo = color; + + lcdCSOn(); + dcHigh(); + + while (w--) { + m_spi.writeByte(hi); + m_spi.writeByte(lo); + } + + lcdCSOff(); +} + +void ILI9341::fillRect(int16_t x, + int16_t y, + int16_t w, + int16_t h, + uint16_t color) { + + // rudimentary clipping (drawChar w/big text requires this) + if((x >= _width) || (y >= _height)) return; + if((x + w - 1) >= _width) w = _width - x; + if((y + h - 1) >= _height) h = _height - y; + + setAddrWindow(x, y, x+w-1, y+h-1); + + uint8_t hi = color >> 8; + uint8_t lo = color; + + lcdCSOn(); + dcHigh(); + + for(y = h; y > 0; y--) { + for(x = w; x > 0; x--) { + m_spi.writeByte(hi); + m_spi.writeByte(lo); + } + } + + lcdCSOff(); +} + +void ILI9341::fillScreen(uint16_t color) { + fillRect(0, 0, _width, _height, color); +} + +void ILI9341::invertDisplay(bool i) { + writecommand(i ? ILI9341_INVON : ILI9341_INVOFF); +} + +uint16_t ILI9341::color565(uint8_t r, uint8_t g, uint8_t b) { + return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); +} + +void ILI9341::executeCMDList(const uint8_t *addr) { + uint8_t numCommands, numArgs; + uint16_t ms; + + numCommands = *(addr++); // Number of commands to follow + while (numCommands--) { // For each command... + writecommand(*(addr++)); // Read, issue command + numArgs = *(addr++); // Number of args to follow + ms = numArgs & DELAY; // If hibit set, delay follows args + numArgs &= ~DELAY; // Mask out delay bit + while (numArgs--) { // For each argument... + writedata(*(addr++)); // Read, issue argument + } + + if (ms) { + ms = *(addr++); // Read post-command delay time (ms) + if (ms == 255) { + ms = 500; // If 255, delay for 500 ms + } + usleep(ms * 1000); + } + } +} + +void ILI9341::writecommand(uint8_t c) { + lcdCSOn(); + dcLow(); + m_spi.writeByte(c); + lcdCSOff(); +} + +void ILI9341::writedata(uint8_t d) { + lcdCSOn(); + dcHigh(); + m_spi.writeByte(d); + lcdCSOff(); +} + +mraa::Result ILI9341::lcdCSOn() { + mraa::Result error = mraa::SUCCESS; + + error = m_csLCDPinCtx.write(LOW); + if (error != mraa::SUCCESS) { + mraa::printError (error); + } + + error = m_csSDPinCtx.write(HIGH); + if (error != mraa::SUCCESS) { + mraa::printError (error); + } + + return error; +} + +mraa::Result ILI9341::lcdCSOff() { + mraa::Result error = mraa::SUCCESS; + + error = m_csLCDPinCtx.write(HIGH); + if (error != mraa::SUCCESS) { + mraa::printError (error); + } + + return error; +} + +mraa::Result ILI9341::sdCSOn() { + mraa::Result error = mraa::SUCCESS; + + error = m_csSDPinCtx.write(LOW); + if (error != mraa::SUCCESS) { + mraa::printError (error); + } + + error = m_csLCDPinCtx.write(HIGH); + if (error != mraa::SUCCESS) { + mraa::printError (error); + } + + return error; +} + +mraa::Result ILI9341::sdCSOff() { + mraa::Result error = mraa::SUCCESS; + + error = m_csSDPinCtx.write(HIGH); + if (error != mraa::SUCCESS) { + mraa::printError (error); + } + + return error; +} + +mraa::Result ILI9341::dcHigh() { + mraa::Result error = mraa::SUCCESS; + + error = m_dcPinCtx.write(HIGH); + if (error != mraa::SUCCESS) { + mraa::printError(error); + } + + return error; +} + +mraa::Result ILI9341::dcLow() { + mraa::Result error = mraa::SUCCESS; + + error = m_dcPinCtx.write(LOW); + if (error != mraa::SUCCESS) { + mraa::printError(error); + } + + return error; +} + +mraa::Result ILI9341::rstHigh() { + mraa::Result error = mraa::SUCCESS; + + error = m_rstPinCtx.write(HIGH); + if (error != mraa::SUCCESS) { + mraa::printError(error); + } + + return error; +} + +mraa::Result ILI9341::rstLow() { + mraa::Result error = mraa::SUCCESS; + + error = m_rstPinCtx.write(LOW); + if (error != mraa::SUCCESS) { + mraa::printError(error); + } + + return error; +} \ No newline at end of file diff --git a/src/ili9341/ili9341.h b/src/ili9341/ili9341.h new file mode 100644 index 00000000..fb2d341b --- /dev/null +++ b/src/ili9341/ili9341.h @@ -0,0 +1,345 @@ +/* + * Author: Shawn Hymel + * Copyright (c) 2015 SparkFun Electronics + * + * Credits to Adafruit. + * Based on Adafruit ILI9341 library, see original license in license.txt file. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +// Includes +#include +#include +#include +#include +#include + +// Defines +#define ILI9341_TFTWIDTH 240 +#define ILI9341_TFTHEIGHT 320 + +#define SPI_FREQ 15000000 + +#define ILI9341_NOP 0x00 +#define ILI9341_SWRESET 0x01 +#define ILI9341_RDDID 0x04 +#define ILI9341_RDDST 0x09 + +#define ILI9341_SLPIN 0x10 +#define ILI9341_SLPOUT 0x11 +#define ILI9341_PTLON 0x12 +#define ILI9341_NORON 0x13 + +#define ILI9341_RDMODE 0x0A +#define ILI9341_RDMADCTL 0x0B +#define ILI9341_RDPIXFMT 0x0C +#define ILI9341_RDIMGFMT 0x0D +#define ILI9341_RDSELFDIAG 0x0F + +#define ILI9341_INVOFF 0x20 +#define ILI9341_INVON 0x21 +#define ILI9341_GAMMASET 0x26 +#define ILI9341_DISPOFF 0x28 +#define ILI9341_DISPON 0x29 + +#define ILI9341_CASET 0x2A +#define ILI9341_PASET 0x2B +#define ILI9341_RAMWR 0x2C +#define ILI9341_RAMRD 0x2E + +#define ILI9341_PTLAR 0x30 +#define ILI9341_MADCTL 0x36 +#define ILI9341_PIXFMT 0x3A + +#define ILI9341_FRMCTR1 0xB1 +#define ILI9341_FRMCTR2 0xB2 +#define ILI9341_FRMCTR3 0xB3 +#define ILI9341_INVCTR 0xB4 +#define ILI9341_DFUNCTR 0xB6 + +#define ILI9341_PWCTR1 0xC0 +#define ILI9341_PWCTR2 0xC1 +#define ILI9341_PWCTR3 0xC2 +#define ILI9341_PWCTR4 0xC3 +#define ILI9341_PWCTR5 0xC4 +#define ILI9341_VMCTR1 0xC5 +#define ILI9341_VMCTR2 0xC7 + +#define ILI9341_RDID1 0xDA +#define ILI9341_RDID2 0xDB +#define ILI9341_RDID3 0xDC +#define ILI9341_RDID4 0xDD + +#define ILI9341_GMCTRP1 0xE0 +#define ILI9341_GMCTRN1 0xE1 + +#define 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 + +#define HIGH 1 +#define LOW 0 + +#define DELAY 0x80 + +// Color definitions +#define ILI9341_BLACK 0x0000 /* 0, 0, 0 */ +#define ILI9341_NAVY 0x000F /* 0, 0, 128 */ +#define ILI9341_DARKGREEN 0x03E0 /* 0, 128, 0 */ +#define ILI9341_DARKCYAN 0x03EF /* 0, 128, 128 */ +#define ILI9341_MAROON 0x7800 /* 128, 0, 0 */ +#define ILI9341_PURPLE 0x780F /* 128, 0, 128 */ +#define ILI9341_OLIVE 0x7BE0 /* 128, 128, 0 */ +#define ILI9341_LIGHTGREY 0xC618 /* 192, 192, 192 */ +#define ILI9341_DARKGREY 0x7BEF /* 128, 128, 128 */ +#define ILI9341_BLUE 0x001F /* 0, 0, 255 */ +#define ILI9341_GREEN 0x07E0 /* 0, 255, 0 */ +#define ILI9341_CYAN 0x07FF /* 0, 255, 255 */ +#define ILI9341_RED 0xF800 /* 255, 0, 0 */ +#define ILI9341_MAGENTA 0xF81F /* 255, 0, 255 */ +#define ILI9341_YELLOW 0xFFE0 /* 255, 255, 0 */ +#define ILI9341_WHITE 0xFFFF /* 255, 255, 255 */ +#define ILI9341_ORANGE 0xFD20 /* 255, 165, 0 */ +#define ILI9341_GREENYELLOW 0xAFE5 /* 173, 255, 47 */ +#define ILI9341_PINK 0xF81F + +namespace upm { + + /** + * @brief ILI9341 LCD library + * @defgroup ili9341 libupm-ili9341 + * @ingroup adafruit spi display + */ + /** + * @library ili9341 + * @sensor ili9341 + * @comname ILI9341 LCD + * @type display + * @man adafruit + * @web http://www.adafruit.com/product/2090 + * @con spi + * + * @brief API for the ILI9342 LCd + * + * This module defines the interface for the ILI9341 display library + * + * @image html ili9341.jpg + * @snippet ili9341.cxx Interesting + */ + class ILI9341 : public GFX { + public: + /** + * Instantiates an ILI9341 object + * + * @param csLCD LCD chip select pin + * @param csSD SD card select pin + * @param dc Data/command pin + * @param rst Reset pin + */ + ILI9341(uint8_t csLCD, uint8_t csSD, uint8_t dc, uint8_t rst); + + /** + * Returns the name of the component + */ + std::string name() { + return m_name; + } + + /** + * Initializes GPIOs used to talk to the LCD + */ + void initModule(); + + /** + * Configures the LCD driver chip via SPI + */ + void configModule(); + + /** + * Sets the window size inside the screen where pixel data is + * written. Concrete implementation from GFX interface. + * + * @param x0 First coordinate + * @param y0 First coordinate + * @param x1 Second coordinate + * @param y1 Second coordinate + */ + void setAddrWindow(uint16_t x0, + uint16_t y0, + uint16_t x1, + uint16_t y1); + + /** + * Sends a pixel color (RGB) to the driver chip. Concrete + * implementation from GFX interface. + * + * @param x Axis on the horizontal scale + * @param y Axis on the vertical scale + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void drawPixel(int16_t x, int16_t y, uint16_t color); + + /** + * Draws a vertical line using minimal SPI writes. + * + * @param x Axis on the horizontal scale to begin line + * @param y Axis on the vertical scale to begin line + * @param h Height of line in pixels + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); + + /** + * Draws a horizontal line using minimal SPI writes. + * + * @param x Axis on the horizontal scale to begin line + * @param y Axis on the vertical scale to begin line + * @param w Width of line in pixels + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); + + /** + * Draw a filled rectangle. + * + * @param x Axis on the horizontal scale of upper-left corner + * @param y Axis on the vertical scale of upper-left corner + * @param w Width of rectangle in pixels + * @param h Height of rectangle in pixels + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void fillRect(int16_t x, + int16_t y, + int16_t w, + int16_t h, + uint16_t color); + + /** + * Fill the screen with a single color. + * + * @param color RGB (16-bit) color (R[0-4], G[5-10], B[11-15] + */ + void fillScreen(uint16_t color); + + /** + * Sets the screen to one of four 90 deg rotations. + * + * @param r Rotation setting: 0, 1, 2, 3 + */ + void setRotation(uint8_t r); + + /** + * Invert colors on the display. + * + * @param i True or false to invert colors + */ + void invertDisplay(bool i); + + /** + * Pass 8-bit R, G, B values and get back 16-bit packed color. + * + * @param r Red color 0-31 + * @param g Green color 0-63 + * @param b blue color 0-31 + * @return 16-bit packed color (RGB) value + */ + uint16_t color565(uint8_t r, uint8_t g, uint8_t b); + + /** + * Executes a set of commands and data. + * + * @param addr Pointer to the start of the commands/data section + */ + void executeCMDList(const uint8_t *addr); + + /** + * Sends a command to the display driver via SPI. + * + * @param c Command to be written + */ + void writecommand(uint8_t c); + + /** + * Sends data to the display driver via SPI + * + * @param d Data to be written + */ + void writedata(uint8_t d); + + /** + * Set LCD chip select to LOW + */ + mraa::Result lcdCSOn(); + + /** + * Set LCD chip select to HIGH + */ + mraa::Result lcdCSOff(); + + /** + * Set SD card chip select to LOW + */ + mraa::Result sdCSOn(); + + /** + * Set SD card chip select to HIGH + */ + mraa::Result sdCSOff(); + + /** + * Set data/command line to HIGH + */ + mraa::Result dcHigh(); + + /** + * Set data/command line to LOW + */ + mraa::Result dcLow(); + + /** + * Set reset line to HIGH + */ + mraa::Result rstHigh(); + + /** + * Set reset line to LOW + */ + mraa::Result rstLow(); + + private: + mraa::Spi m_spi; + uint8_t m_spiBuffer[32]; + + mraa::Gpio m_csLCDPinCtx; + mraa::Gpio m_csSDPinCtx; + mraa::Gpio m_dcPinCtx; + mraa::Gpio m_rstPinCtx; + + std::string m_name; + }; +} + diff --git a/src/ili9341/jsupm_ili9341.i b/src/ili9341/jsupm_ili9341.i new file mode 100644 index 00000000..db58074c --- /dev/null +++ b/src/ili9341/jsupm_ili9341.i @@ -0,0 +1,12 @@ +%module jsupm_ili9341 +%include "../upm.i" + +%include "gfx.h" +%{ + #include "gfx.h" +%} + +%include "ili9341.h" +%{ + #include "ili9341.h" +%} diff --git a/src/ili9341/pyupm_ili9341.i b/src/ili9341/pyupm_ili9341.i new file mode 100644 index 00000000..d8cb1d74 --- /dev/null +++ b/src/ili9341/pyupm_ili9341.i @@ -0,0 +1,16 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_ili9341 +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "gfx.h" +%{ + #include "gfx.h" +%} + +%include "ili9341.h" +%{ + #include "ili9341.h" +%}