mirror of
https://github.com/eclipse/upm.git
synced 2025-03-19 23:17:29 +03:00

To make room for UPM C and C++ sensor code to coexist, all UPM C++ headers have been renamed from h -> hpp. This commit contains updates to documentation, includes, cmake collateral, examples, and swig interface files. * Renamed all cxx/cpp header files which contain the string 'copyright intel' from .h -> .hpp (if not already hpp). * Replaced all references to .h with .hpp in documentation, source files, cmake collateral, example code, and swig interface files. * Replaced cmake variable module_h with module_hpp. * Intentionally left upm.h since this file currently does not contain code (documentation only). Signed-off-by: Noel Eck <noel.eck@intel.com>
487 lines
11 KiB
C++
487 lines
11 KiB
C++
/*
|
|
* 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 <iostream>
|
|
#include <string>
|
|
#include <stdexcept>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "ili9341.hpp"
|
|
|
|
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;
|
|
} |