diff --git a/sys/pic32/gpanel/Adafruit_ILI9341_8bit_AS.cpp b/sys/pic32/gpanel/Adafruit_ILI9341_8bit_AS.cpp new file mode 100644 index 0000000..fcd22ea --- /dev/null +++ b/sys/pic32/gpanel/Adafruit_ILI9341_8bit_AS.cpp @@ -0,0 +1,579 @@ +// IMPORTANT: LIBRARY MUST BE SPECIFICALLY CONFIGURED FOR EITHER TFT SHIELD +// OR BREAKOUT BOARD USAGE. SEE RELEVANT COMMENTS IN Adafruit_ILI9341_8bit_AS.h + +// Graphics library by ladyada/adafruit with init code from Rossum +// MIT license + +#include + +#include "pins_arduino.h" + +#include "wiring_private.h" +#include "Adafruit_ILI9341_8bit_AS.h" + +#if defined __AVR_ATmega328P__ + #include "pin_magic_UNO.h" +#endif + +#if defined __AVR_ATmega2560__ + #include "pin_magic_MEGA.h" +#endif + + +//#define TFTWIDTH 320 +//#define TFTHEIGHT 480 + +#define TFTWIDTH 240 +#define TFTHEIGHT 320 + +// LCD controller chip identifiers +#define ID_9341 2 + +#include "registers.h" + +// Constructor for breakout board (configurable LCD control lines). +// Can still use this w/shield, but parameters are ignored. + +Adafruit_ILI9341_8bit_AS::Adafruit_ILI9341_8bit_AS(uint8_t cs, uint8_t cd, uint8_t wr, uint8_t rd, uint8_t reset) : Adafruit_GFX_AS(TFTWIDTH, TFTHEIGHT) { + +#ifndef USE_ADAFRUIT_SHIELD_PINOUT + // Convert pin numbers to registers and bitmasks + _reset = reset; + + csPort = portOutputRegister(digitalPinToPort(cs)); + cdPort = portOutputRegister(digitalPinToPort(cd)); + wrPort = portOutputRegister(digitalPinToPort(wr)); + rdPort = portOutputRegister(digitalPinToPort(rd)); + + csPinSet = digitalPinToBitMask(cs); + cdPinSet = digitalPinToBitMask(cd); + wrPinSet = digitalPinToBitMask(wr); + rdPinSet = digitalPinToBitMask(rd); + csPinUnset = ~csPinSet; + cdPinUnset = ~cdPinSet; + wrPinUnset = ~wrPinSet; + rdPinUnset = ~rdPinSet; + + *csPort |= csPinSet; // Set all control bits to HIGH (idle) + *cdPort |= cdPinSet; // Signals are ACTIVE LOW + *wrPort |= wrPinSet; + *rdPort |= rdPinSet; + + pinMode(cs, OUTPUT); // Enable outputs + pinMode(cd, OUTPUT); + pinMode(wr, OUTPUT); + pinMode(rd, OUTPUT); + + if(reset) { + digitalWrite(reset, HIGH); + pinMode(reset, OUTPUT); + } +#endif + + init(); +} + +// Constructor for shield (fixed LCD control lines) +Adafruit_ILI9341_8bit_AS::Adafruit_ILI9341_8bit_AS(void) : Adafruit_GFX_AS(TFTWIDTH, TFTHEIGHT) { + init(); +} + +// Initialization common to both shield & breakout configs +void Adafruit_ILI9341_8bit_AS::init(void) { + +#ifdef USE_ADAFRUIT_SHIELD_PINOUT + CS_IDLE; // Set all control bits to idle state + WR_IDLE; + RD_IDLE; + CD_DATA; + digitalWrite(5, HIGH); // Reset line + pinMode(A3, OUTPUT); // Enable outputs + pinMode(A2, OUTPUT); + pinMode(A1, OUTPUT); + pinMode(A0, OUTPUT); + pinMode( 5, OUTPUT); +#endif + + setWriteDir(); // Set up LCD data port(s) for WRITE operations + + rotation = 0; + cursor_y = cursor_x = 0; + textsize = 1; + textcolor = 0xFFFF; + _width = TFTWIDTH; + _height = TFTHEIGHT; +} + +// Initialization command tables for different LCD controllers +#define ILI9341_8bit_AS_DELAY 0xFF +static const uint8_t HX8347G_regValues[] PROGMEM = { + 0x2E , 0x89, + 0x29 , 0x8F, + 0x2B , 0x02, + 0xE2 , 0x00, + 0xE4 , 0x01, + 0xE5 , 0x10, + 0xE6 , 0x01, + 0xE7 , 0x10, + 0xE8 , 0x70, + 0xF2 , 0x00, + 0xEA , 0x00, + 0xEB , 0x20, + 0xEC , 0x3C, + 0xED , 0xC8, + 0xE9 , 0x38, + 0xF1 , 0x01, + + // skip gamma, do later + + 0x1B , 0x1A, + 0x1A , 0x02, + 0x24 , 0x61, + 0x25 , 0x5C, + + 0x18 , 0x36, + 0x19 , 0x01, + 0x1F , 0x88, + ILI9341_8bit_AS_DELAY , 5 , // delay 5 ms + 0x1F , 0x80, + ILI9341_8bit_AS_DELAY , 5 , + 0x1F , 0x90, + ILI9341_8bit_AS_DELAY , 5 , + 0x1F , 0xD4, + ILI9341_8bit_AS_DELAY , 5 , + 0x17 , 0x05, + + 0x36 , 0x09, + 0x28 , 0x38, + ILI9341_8bit_AS_DELAY , 40 , + 0x28 , 0x3C, + + 0x02 , 0x00, + 0x03 , 0x00, + 0x04 , 0x00, + 0x05 , 0xEF, + 0x06 , 0x00, + 0x07 , 0x00, + 0x08 , 0x01, + 0x09 , 0x3F +}; + +void Adafruit_ILI9341_8bit_AS::begin(uint16_t id) { + uint8_t i = 0; + + reset(); + + delay(200); + + uint16_t a, d; + driver = ID_9341; + CS_ACTIVE; + writeRegister8(ILI9341_SOFTRESET, 0); + delay(50); + writeRegister8(ILI9341_DISPLAYOFF, 0); + + writeRegister8(ILI9341_POWERCONTROL1, 0x23); + writeRegister8(ILI9341_POWERCONTROL2, 0x10); + writeRegister16(ILI9341_VCOMCONTROL1, 0x2B2B); + writeRegister8(ILI9341_VCOMCONTROL2, 0xC0); + writeRegister8(ILI9341_MEMCONTROL, ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR); + writeRegister8(ILI9341_PIXELFORMAT, 0x55); + writeRegister16(ILI9341_FRAMECONTROL, 0x001B); + + writeRegister8(ILI9341_ENTRYMODE, 0x07); + /* writeRegister32(ILI9341_DISPLAYFUNC, 0x0A822700);*/ + + writeRegister8(ILI9341_SLEEPOUT, 0); + delay(150); + writeRegister8(ILI9341_DISPLAYON, 0); + delay(500); + setAddrWindow(0, 0, TFTWIDTH-1, TFTHEIGHT-1); + return; +} + +void Adafruit_ILI9341_8bit_AS::reset(void) { + + CS_IDLE; +// CD_DATA; + WR_IDLE; + RD_IDLE; + +#ifdef USE_ADAFRUIT_SHIELD_PINOUT + digitalWrite(5, LOW); + delay(2); + digitalWrite(5, HIGH); +#else + // if we have a reset pin defined ( _reset ) + if(_reset) { + digitalWrite(_reset, LOW); + delay(2); + digitalWrite(_reset, HIGH); + } +#endif + + // Data transfer sync + CS_ACTIVE; + CD_COMMAND; + write8(0x00); + for(uint8_t i=0; i<3; i++) WR_STROBE; // Three extra 0x00s + CS_IDLE; + + // let the display recover from the reset + delay(500); + +} + +// Sets the LCD address window (and address counter, on 932X). +// Relevant to rect/screen fills and H/V lines. Input coordinates are +// assumed pre-sorted (e.g. x2 >= x1). +void Adafruit_ILI9341_8bit_AS::setAddrWindow(int x1, int y1, int x2, int y2) { + CS_ACTIVE; + uint32_t t; + t = x1; + t <<= 16; + t |= x2; + writeRegister32(ILI9341_COLADDRSET, t); // HX8357D uses same registers! + t = y1; + t <<= 16; + t |= y2; + writeRegister32(ILI9341_PAGEADDRSET, t); // HX8357D uses same registers! + CS_IDLE; +} + +// Fast block fill operation for fillScreen, fillRect, H/V line, etc. +// Requires setAddrWindow() has previously been called to set the fill +// bounds. 'len' is inclusive, MUST be >= 1. +void Adafruit_ILI9341_8bit_AS::flood(uint16_t color, uint32_t len) { + uint16_t blocks; + uint8_t i, hi = color >> 8, + lo = color; + + CS_ACTIVE; + CD_COMMAND; + write8(0x2C); + + // Write first pixel normally, decrement counter by 1 + CD_DATA; + write8(hi); + write8(lo); + len--; + + blocks = (uint16_t)(len / 64); // 64 pixels/block + if(hi == lo) { + // High and low bytes are identical. Leave prior data + // on the port(s) and just toggle the write strobe. + while(blocks--) { + i = 16; // 64 pixels/block / 4 pixels/pass + do { + WR_STROBE; WR_STROBE; WR_STROBE; WR_STROBE; // 2 bytes/pixel + WR_STROBE; WR_STROBE; WR_STROBE; WR_STROBE; // x 4 pixels + } while(--i); + } + // Fill any remaining pixels (1 to 64) + for(i = (uint8_t)len & 63; i--; ) { + WR_STROBE; + WR_STROBE; + } + } else { + while(blocks--) { + i = 16; // 64 pixels/block / 4 pixels/pass + do { + write8(hi); write8(lo); write8(hi); write8(lo); + write8(hi); write8(lo); write8(hi); write8(lo); + } while(--i); + } + for(i = (uint8_t)len & 63; i--; ) { + write8(hi); + write8(lo); + } + } + CS_IDLE; +} + +void Adafruit_ILI9341_8bit_AS::drawFastHLine(int16_t x, int16_t y, int16_t length, + uint16_t color) +{ + int16_t x2; + + // Initial off-screen clipping + if((length <= 0 ) || + (y < 0 ) || ( y >= _height) || + (x >= _width) || ((x2 = (x+length-1)) < 0 )) return; + + if(x < 0) { // Clip left + length += x; + x = 0; + } + if(x2 >= _width) { // Clip right + x2 = _width - 1; + length = x2 - x + 1; + } + + setAddrWindow(x, y, x2, y); + flood(color, length); +} + +void Adafruit_ILI9341_8bit_AS::drawFastVLine(int16_t x, int16_t y, int16_t length, + uint16_t color) +{ + int16_t y2; + + // Initial off-screen clipping + if((length <= 0 ) || + (x < 0 ) || ( x >= _width) || + (y >= _height) || ((y2 = (y+length-1)) < 0 )) return; + if(y < 0) { // Clip top + length += y; + y = 0; + } + if(y2 >= _height) { // Clip bottom + y2 = _height - 1; + length = y2 - y + 1; + } + + setAddrWindow(x, y, x, y2); + flood(color, length); +} + +void Adafruit_ILI9341_8bit_AS::fillRect(int16_t x1, int16_t y1, int16_t w, int16_t h, + uint16_t fillcolor) { + int16_t x2, y2; + + // Initial off-screen clipping + if( (w <= 0 ) || (h <= 0 ) || + (x1 >= _width) || (y1 >= _height) || + ((x2 = x1+w-1) < 0 ) || ((y2 = y1+h-1) < 0 )) return; + if(x1 < 0) { // Clip left + w += x1; + x1 = 0; + } + if(y1 < 0) { // Clip top + h += y1; + y1 = 0; + } + if(x2 >= _width) { // Clip right + x2 = _width - 1; + w = x2 - x1 + 1; + } + if(y2 >= _height) { // Clip bottom + y2 = _height - 1; + h = y2 - y1 + 1; + } + + setAddrWindow(x1, y1, x2, y2); + flood(fillcolor, (uint32_t)w * (uint32_t)h); +} + +void Adafruit_ILI9341_8bit_AS::fillScreen(uint16_t color) { + + // For these, there is no settable address pointer, instead the + // address window must be set for each drawing operation. However, + // this display takes rotation into account for the parameters, no + // need to do extra rotation math here. + setAddrWindow(0, 0, _width - 1, _height - 1); + flood(color, (long)TFTWIDTH * (long)TFTHEIGHT); +} + +void Adafruit_ILI9341_8bit_AS::drawPixel(int16_t x, int16_t y, uint16_t color) { + + // Clip + if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return; + + CS_ACTIVE; + setAddrWindow(x, y, _width-1, _height-1); + CS_ACTIVE; + CD_COMMAND; + write8(0x2C); + CD_DATA; + write8(color >> 8); write8(color); + CS_IDLE; +} + +// Issues 'raw' an array of 16-bit color values to the LCD; used +// externally by BMP examples. Assumes that setWindowAddr() has +// previously been set to define the bounds. Max 255 pixels at +// a time (BMP examples read in small chunks due to limited RAM). +void Adafruit_ILI9341_8bit_AS::pushColors(uint16_t *data, uint8_t len, boolean first) { + uint16_t color; + uint8_t hi, lo; + CS_ACTIVE; + if(first == true) { // Issue GRAM write command only on first call + CD_COMMAND; + + write8(0x2C); + } + CD_DATA; + while(len--) { + color = *data++; + hi = color >> 8; // Don't simplify or merge these + lo = color; // lines, there's macro shenanigans + write8(hi); // going on. + write8(lo); + } + CS_IDLE; +} + +void Adafruit_ILI9341_8bit_AS::setRotation(uint8_t x) { + + // Call parent rotation func first -- sets up rotation flags, etc. + Adafruit_GFX_AS::setRotation(x); + // Then perform hardware-specific rotation operations... + + CS_ACTIVE; + uint16_t t; + + switch (rotation) { + case 2: + t = ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR; + break; + case 3: + t = ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR; + break; + case 0: + t = ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR; + break; + case 1: + t = ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR; + break; + } + writeRegister8(ILI9341_MADCTL, t ); // MADCTL + // For 9341, init default full-screen address window: + setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here + + writeRegister8(ILI9341_MADCTL, t ); // MADCTL + // For 8357, init default full-screen address window: + setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here + } + +#ifdef read8isFunctionalized + #define read8(x) x=read8fn() +#endif + +// Because this function is used infrequently, it configures the ports for +// the read operation, reads the data, then restores the ports to the write +// configuration. Write operations happen a LOT, so it's advantageous to +// leave the ports in that state as a default. +uint16_t Adafruit_ILI9341_8bit_AS::readPixel(int16_t x, int16_t y) { + +return 0; +} + +// Ditto with the read/write port directions, as above. +uint16_t Adafruit_ILI9341_8bit_AS::readID(void) { + uint16_t id = readReg(0xD3); + return id; +} + +uint32_t Adafruit_ILI9341_8bit_AS::readReg(uint8_t r) { + uint32_t id; + uint8_t x; + + // try reading register #4 + CS_ACTIVE; + CD_COMMAND; + write8(r); + setReadDir(); // Set up LCD data port(s) for READ operations + CD_DATA; + delayMicroseconds(50); + read8(x); + id = x; // Do not merge or otherwise simplify + id <<= 8; // these lines. It's an unfortunate + read8(x); + id |= x; // shenanigans that are going on. + id <<= 8; // these lines. It's an unfortunate + read8(x); + id |= x; // shenanigans that are going on. + id <<= 8; // these lines. It's an unfortunate + read8(x); + id |= x; // shenanigans that are going on. + CS_IDLE; + setWriteDir(); // Restore LCD data port(s) to WRITE configuration + + return id; +} + +// Pass 8-bit (each) R,G,B, get back 16-bit packed color +uint16_t Adafruit_ILI9341_8bit_AS::color565(uint8_t r, uint8_t g, uint8_t b) { + return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); +} + +// For I/O macros that were left undefined, declare function +// versions that reference the inline macros just once: + +#ifndef write8 +void Adafruit_ILI9341_8bit_AS::write8(uint8_t value) { + write8inline(value); +} +#endif + +#ifdef read8isFunctionalized +uint8_t Adafruit_ILI9341_8bit_AS::read8fn(void) { + uint8_t result; + read8inline(result); + return result; +} +#endif + +#ifndef setWriteDir +void Adafruit_ILI9341_8bit_AS::setWriteDir(void) { + setWriteDirInline(); +} +#endif + +#ifndef setReadDir +void Adafruit_ILI9341_8bit_AS::setReadDir(void) { + setReadDirInline(); +} +#endif + +#ifndef writeRegister8 +void Adafruit_ILI9341_8bit_AS::writeRegister8(uint8_t a, uint8_t d) { + writeRegister8inline(a, d); +} +#endif + +#ifndef writeRegister16 +void Adafruit_ILI9341_8bit_AS::writeRegister16(uint16_t a, uint16_t d) { + writeRegister16inline(a, d); +} +#endif + +#ifndef writeRegisterPair +void Adafruit_ILI9341_8bit_AS::writeRegisterPair(uint8_t aH, uint8_t aL, uint16_t d) { + writeRegisterPairInline(aH, aL, d); +} +#endif + + +void Adafruit_ILI9341_8bit_AS::writeRegister24(uint8_t r, uint32_t d) { + CS_ACTIVE; + CD_COMMAND; + write8(r); + CD_DATA; + delayMicroseconds(10); + write8(d >> 16); + delayMicroseconds(10); + write8(d >> 8); + delayMicroseconds(10); + write8(d); + CS_IDLE; + +} + + +void Adafruit_ILI9341_8bit_AS::writeRegister32(uint8_t r, uint32_t d) { + CS_ACTIVE; + CD_COMMAND; + write8(r); + CD_DATA; + delayMicroseconds(10); + write8(d >> 24); + delayMicroseconds(10); + write8(d >> 16); + delayMicroseconds(10); + write8(d >> 8); + delayMicroseconds(10); + write8(d); + CS_IDLE; + +} diff --git a/sys/pic32/gpanel/Adafruit_ILI9341_8bit_AS.h b/sys/pic32/gpanel/Adafruit_ILI9341_8bit_AS.h new file mode 100644 index 0000000..ec1f8b8 --- /dev/null +++ b/sys/pic32/gpanel/Adafruit_ILI9341_8bit_AS.h @@ -0,0 +1,105 @@ +// IMPORTANT: SEE COMMENTS @ LINE 15 REGARDING SHIELD VS BREAKOUT BOARD USAGE. + +// Graphics library by ladyada/adafruit with init code from Rossum +// MIT license + +#ifndef _ADAFRUIT_ILI9341_8bit_AS_H_ +#define _ADAFRUIT_ILI9341_8bit_AS_H_ + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include "Adafruit_GFX_AS.h" + +// **** IF USING THE LCD BREAKOUT BOARD, COMMENT OUT THIS NEXT LINE. **** +// **** IF USING THE LCD SHIELD, LEAVE THE LINE ENABLED: **** + +//#define USE_ADAFRUIT_SHIELD_PINOUT 1 + +class Adafruit_ILI9341_8bit_AS : public Adafruit_GFX_AS { + + public: + + Adafruit_ILI9341_8bit_AS(uint8_t cs, uint8_t cd, uint8_t wr, uint8_t rd, uint8_t rst); + Adafruit_ILI9341_8bit_AS(void); + + void begin(uint16_t id = 0x9325); + void drawPixel(int16_t x, int16_t y, uint16_t color); + void drawFastHLine(int16_t x0, int16_t y0, int16_t w, uint16_t color); + void drawFastVLine(int16_t x0, int16_t y0, int16_t h, uint16_t color); + void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t c); + void fillScreen(uint16_t color); + void reset(void); + void setRegisters8(uint8_t *ptr, uint8_t n); + void setRegisters16(uint16_t *ptr, uint8_t n); + void setRotation(uint8_t x); + // These methods are public in order for BMP examples to work: + void setAddrWindow(int x1, int y1, int x2, int y2); + void pushColors(uint16_t *data, uint8_t len, boolean first); + + uint16_t color565(uint8_t r, uint8_t g, uint8_t b), + readPixel(int16_t x, int16_t y), + readID(void); + uint32_t readReg(uint8_t r); + + private: + + void init(), + // These items may have previously been defined as macros + // in pin_magic.h. If not, function versions are declared: +#ifndef write8 + write8(uint8_t value), +#endif +#ifndef setWriteDir + setWriteDir(void), +#endif +#ifndef setReadDir + setReadDir(void), +#endif +#ifndef writeRegister8 + writeRegister8(uint8_t a, uint8_t d), +#endif +#ifndef writeRegister16 + writeRegister16(uint16_t a, uint16_t d), +#endif + writeRegister24(uint8_t a, uint32_t d), + writeRegister32(uint8_t a, uint32_t d), +#ifndef writeRegisterPair + writeRegisterPair(uint8_t aH, uint8_t aL, uint16_t d), +#endif + setLR(void), + flood(uint16_t color, uint32_t len); + uint8_t driver; + +#ifndef read8 + uint8_t read8fn(void); + #define read8isFunctionalized +#endif + +#ifndef USE_ADAFRUIT_SHIELD_PINOUT + + #ifdef __AVR__ + volatile uint8_t *csPort , *cdPort , *wrPort , *rdPort; + uint8_t csPinSet , cdPinSet , wrPinSet , rdPinSet , + csPinUnset, cdPinUnset, wrPinUnset, rdPinUnset, + _reset; + #endif + #if defined(__SAM3X8E__) + Pio *csPort , *cdPort , *wrPort , *rdPort; + uint32_t csPinSet , cdPinSet , wrPinSet , rdPinSet , + csPinUnset, cdPinUnset, wrPinUnset, rdPinUnset, + _reset; +#endif + +#endif +}; + +// For compatibility with sketches written for older versions of library. +// Color function name was changed to 'color565' for parity with 2.2" LCD +// library. +#define Color565 color565 + +#endif diff --git a/sys/pic32/gpanel/_105_touch_graphicstest.c b/sys/pic32/gpanel/_105_touch_graphicstest.c new file mode 100644 index 0000000..fbf247f --- /dev/null +++ b/sys/pic32/gpanel/_105_touch_graphicstest.c @@ -0,0 +1,375 @@ +// IMPORTANT: Adafruit_ILI9341_8bit_AS LIBRARY MUST BE SPECIFICALLY +// CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD. +// DEFAULT IS THE UNO SHIELD +// SEE RELEVANT COMMENTS IN Adafruit_ILI9341_8bit_AS.h FOR SETUP. + +#define DEBUG +#include // Core graphics library +#include // Hardware-specific library + +// The control pins for the LCD can be assigned to any digital or +// analog pins...but we'll use the analog pins as this allows us to +// double up the pins with the touch screen (see the TFT paint example). +#define LCD_CS A3 // Chip Select goes to Analog 3 +#define LCD_CD A2 // Command/Data goes to Analog 2 +#define LCD_WR A1 // LCD Write goes to Analog 1 +#define LCD_RD A0 // LCD Read goes to Analog 0 + +#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin + +// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD: +// For the Arduino Uno, Duemilanove, Diecimila, etc.: +// D0 connects to digital pin 8 (Notice these are +// D1 connects to digital pin 9 NOT in order!) +// D2 connects to digital pin 2 +// D3 connects to digital pin 3 +// D4 connects to digital pin 4 +// D5 connects to digital pin 5 +// D6 connects to digital pin 6 +// D7 connects to digital pin 7 +// For the Arduino Mega, use digital pins 22 through 29 +// (on the 2-row header at the end of the board). + +// Assign human-readable names to some common 16-bit color values: +#define BLACK 0x0000 +#define BLUE 0x001F +#define RED 0xF800 +#define GREEN 0x07E0 +#define CYAN 0x07FF +#define MAGENTA 0xF81F +#define YELLOW 0xFFE0 +#define WHITE 0xFFFF + +Adafruit_ILI9341_8bit_AS tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); +// If using the shield, all control and data lines are fixed, and +// a simpler declaration can optionally be used: +// Adafruit_ILI9341_8bit_AS tft; + +void setup(void) { + #ifdef DEBUG + Serial.begin(9600); + Serial.println("TFT LCD test"); + Serial.print("TFT size is "); + Serial.print(tft.width()); + Serial.print("x"); + Serial.println(tft.height()); +#endif // DEBUG + + tft.reset(); + delay(10); + tft.begin(0x9341); + +#ifdef DEBUG + Serial.println("Benchmark Time (microseconds)"); + + Serial.print("Screen fill "); + Serial.println(testFillScreen()); + delay(500); + + Serial.print("Text "); + Serial.println(testText()); + delay(3000); + + Serial.print("Lines "); + Serial.println(testLines(CYAN)); + delay(500); + + Serial.print("Horiz/Vert Lines "); + Serial.println(testFastLines(RED, BLUE)); + delay(500); + + Serial.print("Rectangles (outline) "); + Serial.println(testRects(GREEN)); + delay(500); + + Serial.print("Rectangles (filled) "); + Serial.println(testFilledRects(YELLOW, MAGENTA)); + delay(500); + + Serial.print("Circles (filled) "); + Serial.println(testFilledCircles(10, MAGENTA)); + + Serial.print("Circles (outline) "); + Serial.println(testCircles(10, WHITE)); + delay(500); + + Serial.print("Triangles (outline) "); + Serial.println(testTriangles()); + delay(500); + + Serial.print("Triangles (filled) "); + Serial.println(testFilledTriangles()); + delay(500); + + Serial.print("Rounded rects (outline) "); + Serial.println(testRoundRects()); + delay(500); + + Serial.print("Rounded rects (filled) "); + Serial.println(testFilledRoundRects()); + delay(500); + + Serial.println("Done!"); +#endif // DEBUG +} + +void loop(void) { + for(uint8_t rotation=0; rotation<4; rotation++) { + tft.setRotation(rotation); + testText(); + delay(2000); + } + testFilledRoundRects(); + testRoundRects(); + testFilledTriangles(); + testTriangles(); + testCircles(10, WHITE); + testFillScreen(); + testText(); + testLines(CYAN); + testFastLines(RED, BLUE); + testRects(GREEN); + testFilledRects(YELLOW, MAGENTA); + testFilledCircles(10, MAGENTA); +} + +unsigned long testFillScreen() { + unsigned long start = micros(); + tft.fillScreen(BLACK); + tft.fillScreen(RED); + tft.fillScreen(GREEN); + tft.fillScreen(BLUE); + tft.fillScreen(BLACK); + return micros() - start; +} + +unsigned long testText() { + tft.fillScreen(BLACK); + unsigned long start = micros(); + tft.setCursor(0, 0); + tft.setTextColor(WHITE); tft.setTextSize(1); + tft.println("Hello World!"); + tft.setTextColor(YELLOW); tft.setTextSize(2); + tft.println(1234.56); + tft.setTextColor(RED); tft.setTextSize(3); + tft.println(0xDEADBEEF, HEX); + tft.println(); + tft.setTextColor(GREEN); + tft.setTextSize(5); + tft.println("Groop"); + tft.setTextSize(2); + tft.println("I implore thee,"); + tft.setTextSize(1); + tft.println("my foonting turlingdromes."); + tft.println("And hooptiously drangle me"); + tft.println("with crinkly bindlewurdles,"); + tft.println("Or I will rend thee"); + tft.println("in the gobberwarts"); + tft.println("with my blurglecruncheon,"); + tft.println("see if I don't!"); + return micros() - start; +} + +unsigned long testLines(uint16_t color) { + unsigned long start, t; + int x1, y1, x2, y2, + w = tft.width(), + h = tft.height(); + + tft.fillScreen(BLACK); + + x1 = y1 = 0; + y2 = h - 1; + start = micros(); + for(x2=0; x20; i-=6) { + i2 = i / 2; + start = micros(); + tft.fillRect(cx-i2, cy-i2, i, i, color1); + t += micros() - start; + // Outlines are not included in timing results + tft.drawRect(cx-i2, cy-i2, i, i, color2); + } + + return t; +} + +unsigned long testFilledCircles(uint8_t radius, uint16_t color) { + unsigned long start; + int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2; + + tft.fillScreen(BLACK); + start = micros(); + for(x=radius; x10; i-=5) { + start = micros(); + tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, + tft.color565(0, i, i)); + t += micros() - start; + tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, + tft.color565(i, i, 0)); + } + + return t; +} + +unsigned long testRoundRects() { + unsigned long start; + int w, i, i2, + cx = tft.width() / 2 - 1, + cy = tft.height() / 2 - 1; + + tft.fillScreen(BLACK); + w = min(tft.width(), tft.height()); + start = micros(); + for(i=0; i20; i-=6) { + i2 = i / 2; + tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0)); + } + + return micros() - start; +} diff --git a/sys/pic32/gpanel/nt35702.c b/sys/pic32/gpanel/nt35702.c new file mode 100644 index 0000000..df520b1 --- /dev/null +++ b/sys/pic32/gpanel/nt35702.c @@ -0,0 +1,330 @@ + +#define LCD_RD A0 +#define LCD_WR A1 +#define LCD_RS A2 +#define LCD_CS A3 +#define LCD_REST A4 + +void Lcd_Writ_Bus(unsigned char VH) +{ + unsigned int i,temp,data; + data=VH; + for (i=8; i<=9; i++) { + temp=(data&0x01); + if (temp) + digitalWrite(i,HIGH); + else + digitalWrite(i,LOW); + data=data>>1; + } + for (i=2; i<=7; i++) { + temp=(data&0x01); + if (temp) + digitalWrite(i,HIGH); + else + digitalWrite(i,LOW); + data=data>>1; + } + + digitalWrite(LCD_WR,LOW); + digitalWrite(LCD_WR,HIGH); +} + +void Lcd_Write_Com(unsigned char VH) +{ + digitalWrite(LCD_RS,LOW); + Lcd_Writ_Bus(VH); +} + +void Lcd_Write_Data(unsigned char VH) +{ + digitalWrite(LCD_RS,HIGH); + Lcd_Writ_Bus(VH); +} + +void Lcd_Write_Com_Data(unsigned char com,unsigned char dat) +{ + Lcd_Write_Com(com); + Lcd_Write_Data(dat); +} + +void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2) +{ + Lcd_Write_Com_Data(0x2a,x1>>8); + Lcd_Write_Com_Data(0x2a,x1); + Lcd_Write_Com_Data(0x2a,x2>>8); + Lcd_Write_Com_Data(0x2a,x2); + Lcd_Write_Com_Data(0x2b,y1>>8); + Lcd_Write_Com_Data(0x2b,y1); + Lcd_Write_Com_Data(0x2b,y2>>8); + Lcd_Write_Com_Data(0x2b,y2); + Lcd_Write_Com(0x2c); +} + +void Lcd_Init(void) +{ + digitalWrite(LCD_REST, HIGH); + delay(5); + digitalWrite(LCD_REST, LOW); + delay(15); + digitalWrite(LCD_REST, HIGH); + delay(15); + + digitalWrite(LCD_CS, HIGH); + digitalWrite(LCD_WR, HIGH); + digitalWrite(LCD_CS, LOW); //CS + Lcd_Write_Com(0x01);// Software Reset + delay(20); + + Lcd_Write_Com(0x11);//Sleep Out + delay(120); + + Lcd_Write_Com(0xc2);//Power Control 3 + Lcd_Write_Data(0x05);//APA2 APA1 APA0 Large + Lcd_Write_Data(0x00);//Step-up cycle in Booster circuit 1 + //Step-up cycle in Booster circuit 2,3 + Lcd_Write_Com(0xc3);//Power Control 4 + Lcd_Write_Data(0x05);//APA2 APA1 APA0 Large + Lcd_Write_Data(0x00);//Step-up cycle in Booster circuit 1 + //Step-up cycle in Booster circuit 2,3 + Lcd_Write_Com(0xc4);//Power Control 5 + Lcd_Write_Data(0x05);//APA2 APA1 APA0 Large + Lcd_Write_Data(0x00);//Step-up cycle in Booster circuit 1 + //Step-up cycle in Booster circuit 2,3 + Lcd_Write_Com(0x3A); + Lcd_Write_Data(0x55); + + Lcd_Write_Com(0xD7); + Lcd_Write_Data(0x40); + Lcd_Write_Data(0xE0); + + Lcd_Write_Com(0xFD); + Lcd_Write_Data(0x06); + Lcd_Write_Data(0x11); + + Lcd_Write_Com(0xFA); + Lcd_Write_Data(0x38); + Lcd_Write_Data(0x20); + Lcd_Write_Data(0x1C); + Lcd_Write_Data(0x10); + Lcd_Write_Data(0x37); + Lcd_Write_Data(0x12); + Lcd_Write_Data(0x22); + Lcd_Write_Data(0x1E); + + Lcd_Write_Com(0xC0);//Set GVDD + Lcd_Write_Data(0x05); + + Lcd_Write_Com(0xC5);//Set Vcom + Lcd_Write_Data(0x60); + Lcd_Write_Data(0x00); + + Lcd_Write_Com(0xC7);//Set VCOM-OFFSET + Lcd_Write_Data(0xA9);// 可以微调改善flicker + + Lcd_Write_Com(0x36);//Memory data access control + Lcd_Write_Data(0xC8);//MY MX MV ML RGB MH 0 0 + + ////Gamma////////////////// + Lcd_Write_Com(0xE0);//E0H Set + Lcd_Write_Data(0x23); + Lcd_Write_Data(0x23); + Lcd_Write_Data(0x24); + Lcd_Write_Data(0x02); + Lcd_Write_Data(0x08); + Lcd_Write_Data(0x0F); + Lcd_Write_Data(0x35); + Lcd_Write_Data(0x7B); + Lcd_Write_Data(0x43); + Lcd_Write_Data(0x0E); + Lcd_Write_Data(0x1F); + Lcd_Write_Data(0x25); + Lcd_Write_Data(0x10); + Lcd_Write_Data(0x16); + Lcd_Write_Data(0x31); + + Lcd_Write_Com(0xE1);//E1H Set + Lcd_Write_Data(0x0D); + Lcd_Write_Data(0x28); + Lcd_Write_Data(0x2E); + Lcd_Write_Data(0x0B); + Lcd_Write_Data(0x11); + Lcd_Write_Data(0x12); + Lcd_Write_Data(0x3E); + Lcd_Write_Data(0x59); + Lcd_Write_Data(0x4C); + Lcd_Write_Data(0x10); + Lcd_Write_Data(0x26); + Lcd_Write_Data(0x2B); + Lcd_Write_Data(0x1B); + Lcd_Write_Data(0x1B); + Lcd_Write_Data(0x1B); + + Lcd_Write_Com(0x29);//display on + + Lcd_Write_Com(0x2c);//Memory Write +} + +void H_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c) +{ + unsigned int i, j; + + Lcd_Write_Com(0x02c); //write_memory_start + digitalWrite(LCD_RS, HIGH); + digitalWrite(LCD_CS, LOW); + l = l+x; + Address_set(x,y,l,y); + j = l*2; + for(i=1;i<=j;i++) + { + Lcd_Write_Data(c>>8); + Lcd_Write_Data(c); + } + digitalWrite(LCD_CS, HIGH); +} + +void V_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c) +{ + unsigned int i, j; + + Lcd_Write_Com(0x02c); //write_memory_start + digitalWrite(LCD_RS, HIGH); + digitalWrite(LCD_CS, LOW); + l = l+y; + Address_set(x,y,x,l); + j = l*2; + for(i=1;i<=j;i++) + { + Lcd_Write_Data(c>>8); + Lcd_Write_Data(c); + } + digitalWrite(LCD_CS, HIGH); +} + +void Rect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c) +{ + H_line(x , y , w, c); + H_line(x , y+h, w, c); + V_line(x , y , h, c); + V_line(x+w, y , h, c); +} + +void Rectf(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c) +{ + unsigned int i; + + for (i=0; i> 3); +} + +void LCD_Clear(unsigned int j) +{ + unsigned int i, m; + + Address_set(0, 0, 320, 240); + Lcd_Write_Com(0x02c); //write_memory_start + digitalWrite(LCD_RS,HIGH); + digitalWrite(LCD_CS,LOW); + + for (i=0; i<320; i++) { + for (m=0; m<240; m++) { + //ch=((fcolorr&248)|fcolorg>>5); + //cl=((fcolorg&28)<<3|fcolorb>>3); + + Lcd_Write_Data(j>>8); + Lcd_Write_Data(j); + } + } + digitalWrite(LCD_CS,HIGH); +} + +void draw_Pixel(int x,int y, unsigned int c) +{ + Address_set(x, y, x, y); + Lcd_Write_Data(c >> 8); + Lcd_Write_Data(c); +} + +void swap(int x, int y) +{ + int temp = x; + x = y; + y = temp; +} + +void draw_Hline(int x, int y, int l,unsigned int c) +{ + Address_set(x, y, x+l, y); + for (int i=0; i> 8); + Lcd_Write_Data(c); + } +} + +void draw_Vline(int x, int y, int l, unsigned int c) +{ + Address_set(x, y, x, y+l); + for (int i=0; i x2) { + swap(x1, x2); + } + if (y1 > y2) { + swap(y1, y2); + } + + if ((x2-x1 > 4 && (y2-y1) > 4) { + draw_Pixel(x1+1,y1+1,c); + draw_Pixel(x2-1,y1+1,c); + draw_Pixel(x1+1,y2-1,c); + draw_Pixel(x2-1,y2-1,c); + draw_Hline(x1+2, y1, x2-x1-4,c); + draw_Hline(x1+2, y2, x2-x1-4,c); + draw_Vline(x1, y1+2, y2-y1-4,c); + draw_Vline(x2, y1+2, y2-y1-4,c); + } +} + +void setup() +{ + for (int p=2; p<10; p++) + pinMode(p, OUTPUT); + + pinMode(A0, OUTPUT); + pinMode(A1, OUTPUT); + pinMode(A2, OUTPUT); + pinMode(A3, OUTPUT); + pinMode(A4, OUTPUT); + digitalWrite(A0, HIGH); + digitalWrite(A1, HIGH); + digitalWrite(A2, HIGH); + digitalWrite(A3, HIGH); + digitalWrite(A4, HIGH); + + Lcd_Init(); + //LCD_Clear(RGB(255, 0, 0)); + //LCD_Clear(RGB(255, 255, 0)); + //LCD_Clear(RGB(255, 0, 255)); + //LCD_Clear(RGB(0, 255, 255)); + //LCD_Clear(RGB(0, 255, 0)); +} diff --git a/sys/pic32/gpanel/pin_magic_MEGA.h b/sys/pic32/gpanel/pin_magic_MEGA.h new file mode 100644 index 0000000..e7c07fc --- /dev/null +++ b/sys/pic32/gpanel/pin_magic_MEGA.h @@ -0,0 +1,126 @@ +#ifndef _pin_magic_ +#define _pin_magic_ +// This header file serves two purposes: +// +// 1) Isolate non-portable MCU port- and pin-specific identifiers and +// operations so the library code itself remains somewhat agnostic +// (PORTs and pin numbers are always referenced through macros). +// +// 2) GCC doesn't always respect the "inline" keyword, so this is a +// ham-fisted manner of forcing the issue to minimize function calls. +// This sometimes makes the library a bit bigger than before, but fast++. +// However, because they're macros, we need to be SUPER CAREFUL about +// parameters -- for example, write8(x) may expand to multiple PORT +// writes that all refer to x, so it needs to be a constant or fixed +// variable and not something like *ptr++ (which, after macro +// expansion, may increment the pointer repeatedly and run off into +// la-la land). Macros also give us fine-grained control over which +// operations are inlined on which boards (balancing speed against +// available program space). +// When using the TFT shield, control and data pins exist in set physical +// locations, but the ports and bitmasks corresponding to each vary among +// boards. A separate set of pin definitions is given for each supported +// board type. +// When using the TFT breakout board, control pins are configurable but +// the data pins are still fixed -- making every data pin configurable +// would be much too slow. The data pin layouts are not the same between +// the shield and breakout configurations -- for the latter, pins were +// chosen to keep the tutorial wiring manageable more than making optimal +// use of ports and bitmasks. So there's a second set of pin definitions +// given for each supported board. +// Shield pin usage: + +// Breakout pin usage: +// LCD Data Bit : 7 6 5 4 3 2 1 0 +// Uno dig. pin : 7 6 5 4 3 2 9 8 +// Uno port/pin : PD7 PD6 PD5 PD4 PD3 PD2 PB1 PB0 +// Mega dig. pin: 27 6 5 4 3 2 9 8 +// Mega port/pin: PH4 PH3 PE3 PG5 PE5 PE4 PH6 PH5 + +// Pixel read operations require a minimum 400 nS delay from RD_ACTIVE +// to polling the input pins. At 16 MHz, one machine cycle is 62.5 nS. +// This code burns 7 cycles (437.5 nS) doing nothing; the RJMPs are +// equivalent to two NOPs each, final NOP burns the 7th cycle, and the +// last line is a radioactive mutant emoticon. +#define DELAY7 \ +asm volatile( \ +"rjmp .+0" "\n\t" \ +"rjmp .+0" "\n\t" \ +"rjmp .+0" "\n\t" \ +"nop" "\n" \ +::); + + +// As part of the inline control, macros reference other macros...if any +// of these are left undefined, an equivalent function version (non-inline) +// is declared later. The Uno has a moderate amount of program space, so +// only write8() is inlined -- that one provides the most performance +// benefit, but unfortunately also generates the most bloat. This is +// why only certain cases are inlined for each board. + + +// Arduino Mega, ADK, etc. +// Mega port/pin: PH4 PH3 PE3 PG5 PE5 PE4 PH6 PH5 +// Because the MEGA port to pin mapping is very messy it is necessary to shift the data bits around a lot. + #define write8inline(d) { \ + PORTE = (PORTE & B11001111) | ((d << 2) & B00110000); \ + PORTE = (PORTE & B11110111) | ((d >> 2) & B00001000); \ + PORTG = (PORTG & B11011111) | ((d << 1) & B00100000); \ + PORTH = (PORTH & B11100111) | ((d >> 3) & B00011000); \ + PORTH = (PORTH & B10011111) | ((d << 5) & B01100000); \ + WR_STROBE; } + #define read8inline(result) { \ + RD_ACTIVE; \ + DELAY7; \ + result = ((PINH & B00011000) << 3) | ((PINE & B00001000) << 2) | ((PING & B00100000) >> 1) |((PINE & B00110000) >> 2) | ((PINH & B01100000) >> 5); \ + RD_IDLE; } + + // // These set the PORT directions as required before the write and read + // // operations. + #define setWriteDirInline() { DDRE |= B00111000; DDRG |= B00100000; DDRH |= B01111000;} + #define setReadDirInline() { DDRE &= ~B00111000; DDRG &= ~B00100000; DDRH &= ~B01111000;} + + +// All of the functions are inlined on the Arduino Mega. When using the +// breakout board, the macro versions aren't appreciably larger than the +// function equivalents, and they're super simple and fast. When using +// the shield, the macros become pretty complicated...but this board has +// so much code space, the macros are used anyway. If you need to free +// up program space, some macros can be removed, at a minor cost in speed. +#define write8 write8inline +#define read8 read8inline +#define setWriteDir setWriteDirInline +#define setReadDir setReadDirInline +#define writeRegister8 writeRegister8inline +#define writeRegister16 writeRegister16inline +#define writeRegisterPair writeRegisterPairInline +// When using the TFT breakout board, control pins are configurable. +#define RD_ACTIVE *rdPort &= rdPinUnset +#define RD_IDLE *rdPort |= rdPinSet +#define WR_ACTIVE *wrPort &= wrPinUnset +#define WR_IDLE *wrPort |= wrPinSet +#define CD_COMMAND *cdPort &= cdPinUnset +#define CD_DATA *cdPort |= cdPinSet +#define CS_ACTIVE *csPort &= csPinUnset +#define CS_IDLE *csPort |= csPinSet +#endif +// Data read and write strobes, ~2 instructions and always inline +#define RD_STROBE { RD_ACTIVE; RD_IDLE; } +#define WR_STROBE { WR_ACTIVE; WR_IDLE; } +// These higher-level operations are usually functionalized, +// except on Mega where's there's gobs and gobs of program space. +// Set value of TFT register: 8-bit address, 8-bit value +#define writeRegister8inline(a, d) { \ +CD_COMMAND; write8(a); CD_DATA; write8(d); } +// Set value of TFT register: 16-bit address, 16-bit value +// See notes at top about macro expansion, hence hi & lo temp vars +#define writeRegister16inline(a, d) { \ +uint8_t hi, lo; \ +hi = (a) >> 8; lo = (a); CD_COMMAND; write8(hi); write8(lo); \ +hi = (d) >> 8; lo = (d); CD_DATA ; write8(hi); write8(lo); } +// Set value of 2 TFT registers: Two 8-bit addresses (hi & lo), 16-bit value +#define writeRegisterPairInline(aH, aL, d) { \ +uint8_t hi = (d) >> 8, lo = (d); \ +CD_COMMAND; write8(aH); CD_DATA; write8(hi); \ +CD_COMMAND; write8(aL); CD_DATA; write8(lo); } + diff --git a/sys/pic32/gpanel/pin_magic_UNO.h b/sys/pic32/gpanel/pin_magic_UNO.h new file mode 100644 index 0000000..d631e6b --- /dev/null +++ b/sys/pic32/gpanel/pin_magic_UNO.h @@ -0,0 +1,117 @@ +#ifndef _pin_magic_ +#define _pin_magic_ +// This header file serves two purposes: +// +// 1) Isolate non-portable MCU port- and pin-specific identifiers and +// operations so the library code itself remains somewhat agnostic +// (PORTs and pin numbers are always referenced through macros). +// +// 2) GCC doesn't always respect the "inline" keyword, so this is a +// ham-fisted manner of forcing the issue to minimize function calls. +// This sometimes makes the library a bit bigger than before, but fast++. +// However, because they're macros, we need to be SUPER CAREFUL about +// parameters -- for example, write8(x) may expand to multiple PORT +// writes that all refer to x, so it needs to be a constant or fixed +// variable and not something like *ptr++ (which, after macro +// expansion, may increment the pointer repeatedly and run off into +// la-la land). Macros also give us fine-grained control over which +// operations are inlined on which boards (balancing speed against +// available program space). +// When using the TFT shield, control and data pins exist in set physical +// locations, but the ports and bitmasks corresponding to each vary among +// boards. A separate set of pin definitions is given for each supported +// board type. +// When using the TFT breakout board, control pins are configurable but +// the data pins are still fixed -- making every data pin configurable +// would be much too slow. The data pin layouts are not the same between +// the shield and breakout configurations -- for the latter, pins were +// chosen to keep the tutorial wiring manageable more than making optimal +// use of ports and bitmasks. So there's a second set of pin definitions +// given for each supported board. +// Shield pin usage: + +// Breakout pin usage: +// LCD Data Bit : 7 6 5 4 3 2 1 0 +// Uno dig. pin : 7 6 5 4 3 2 9 8 +// Uno port/pin : PD7 PD6 PD5 PD4 PD3 PD2 PB1 PB0 +// Mega dig. pin: 27 6 5 4 3 2 9 8 +// Mega port/pin: PH4 PH3 PE3 PG5 PE5 PE4 PH6 PH5 + +// Pixel read operations require a minimum 400 nS delay from RD_ACTIVE +// to polling the input pins. At 16 MHz, one machine cycle is 62.5 nS. +// This code burns 7 cycles (437.5 nS) doing nothing; the RJMPs are +// equivalent to two NOPs each, final NOP burns the 7th cycle, and the +// last line is a radioactive mutant emoticon. +#define DELAY7 \ +asm volatile( \ +"rjmp .+0" "\n\t" \ +"rjmp .+0" "\n\t" \ +"rjmp .+0" "\n\t" \ +"nop" "\n" \ +::); +// As part of the inline control, macros reference other macros...if any +// of these are left undefined, an equivalent function version (non-inline) +// is declared later. The Uno has a moderate amount of program space, so +// only write8() is inlined -- that one provides the most performance +// benefit, but unfortunately also generates the most bloat. This is +// why only certain cases are inlined for each board. +//Uno w/Breakout board +// Uno dig. pin : 7 6 5 4 3 2 9 8 +// Uno port/pin : PD7 PD6 PD5 PD4 PD3 PD2 PB1 PB0 +#define write8inline(d) { \ +PORTD = (PORTD & B00000011) | ((d) & B11111100); \ +PORTB = (PORTB & B11111100) | ((d) & B00000011); \ +WR_STROBE; } +#define read8inline(result) { \ +RD_ACTIVE; \ +DELAY7; \ +result = (PIND & B11111100) | (PINB & B00000011); \ +RD_IDLE; } +#define setWriteDirInline() { DDRD |= B11111100; DDRB |= B00000011; } +#define setReadDirInline() { DDRD &= ~B11111100; DDRB &= ~B00000011; } + + + +// All of the functions are inlined on the Arduino Mega. When using the +// breakout board, the macro versions aren't appreciably larger than the +// function equivalents, and they're super simple and fast. When using +// the shield, the macros become pretty complicated...but this board has +// so much code space, the macros are used anyway. If you need to free +// up program space, some macros can be removed, at a minor cost in speed. +#define write8 write8inline +#define read8 read8inline +#define setWriteDir setWriteDirInline +#define setReadDir setReadDirInline +#define writeRegister8 writeRegister8inline +#define writeRegister16 writeRegister16inline +#define writeRegisterPair writeRegisterPairInline +// When using the TFT breakout board, control pins are configurable. +#define RD_ACTIVE *rdPort &= rdPinUnset +#define RD_IDLE *rdPort |= rdPinSet +#define WR_ACTIVE *wrPort &= wrPinUnset +#define WR_IDLE *wrPort |= wrPinSet +#define CD_COMMAND *cdPort &= cdPinUnset +#define CD_DATA *cdPort |= cdPinSet +#define CS_ACTIVE *csPort &= csPinUnset +#define CS_IDLE *csPort |= csPinSet +#endif +// Data read and write strobes, ~2 instructions and always inline +#define RD_STROBE { RD_ACTIVE; RD_IDLE; } +#define WR_STROBE { WR_ACTIVE; WR_IDLE; } +// These higher-level operations are usually functionalized, +// except on Mega where's there's gobs and gobs of program space. +// Set value of TFT register: 8-bit address, 8-bit value +#define writeRegister8inline(a, d) { \ +CD_COMMAND; write8(a); CD_DATA; write8(d); } +// Set value of TFT register: 16-bit address, 16-bit value +// See notes at top about macro expansion, hence hi & lo temp vars +#define writeRegister16inline(a, d) { \ +uint8_t hi, lo; \ +hi = (a) >> 8; lo = (a); CD_COMMAND; write8(hi); write8(lo); \ +hi = (d) >> 8; lo = (d); CD_DATA ; write8(hi); write8(lo); } +// Set value of 2 TFT registers: Two 8-bit addresses (hi & lo), 16-bit value +#define writeRegisterPairInline(aH, aL, d) { \ +uint8_t hi = (d) >> 8, lo = (d); \ +CD_COMMAND; write8(aH); CD_DATA; write8(hi); \ +CD_COMMAND; write8(aL); CD_DATA; write8(lo); } + diff --git a/sys/pic32/gpanel/registers.h b/sys/pic32/gpanel/registers.h new file mode 100644 index 0000000..4ad78de --- /dev/null +++ b/sys/pic32/gpanel/registers.h @@ -0,0 +1,30 @@ +#define ILI9341_SOFTRESET 0x01 +#define ILI9341_SLEEPIN 0x10 +#define ILI9341_SLEEPOUT 0x11 +#define ILI9341_NORMALDISP 0x13 +#define ILI9341_INVERTOFF 0x20 +#define ILI9341_INVERTON 0x21 +#define ILI9341_GAMMASET 0x26 +#define ILI9341_DISPLAYOFF 0x28 +#define ILI9341_DISPLAYON 0x29 +#define ILI9341_COLADDRSET 0x2A +#define ILI9341_PAGEADDRSET 0x2B +#define ILI9341_MEMORYWRITE 0x2C +#define ILI9341_MEMCONTROL 0x36 +#define ILI9341_MADCTL 0x36 +#define ILI9341_PIXELFORMAT 0x3A +#define ILI9341_FRAMECONTROL 0xB1 +#define ILI9341_DISPLAYFUNC 0xB6 +#define ILI9341_ENTRYMODE 0xB7 +#define ILI9341_POWERCONTROL1 0xC0 +#define ILI9341_POWERCONTROL2 0xC1 +#define ILI9341_VCOMCONTROL1 0xC5 +#define ILI9341_VCOMCONTROL2 0xC7 + +#define ILI9341_MADCTL_MY 0x80 +#define ILI9341_MADCTL_MX 0x40 +#define ILI9341_MADCTL_MV 0x20 +#define ILI9341_MADCTL_ML 0x10 +#define ILI9341_MADCTL_BGR 0x08 +#define ILI9341_MADCTL_MH 0x04 +#define ILI9341_MADCTL_RGB 0x00