From 1ac4e022a34808dd1268cfc612baf87dad220b4b Mon Sep 17 00:00:00 2001 From: ladyada Date: Mon, 9 Sep 2013 15:37:55 -0400 Subject: [PATCH] init --- Adafruit_RA8875.cpp | 314 ++++++++++++++++++++++++++++++++++++++++++++ Adafruit_RA8875.h | 248 ++++++++++++++++++++++++++++++++++ 2 files changed, 562 insertions(+) create mode 100644 Adafruit_RA8875.cpp create mode 100644 Adafruit_RA8875.h diff --git a/Adafruit_RA8875.cpp b/Adafruit_RA8875.cpp new file mode 100644 index 0000000..4e01035 --- /dev/null +++ b/Adafruit_RA8875.cpp @@ -0,0 +1,314 @@ +#include +#include +#include "Adafruit_RA8875.h" + +Adafruit_RA8875::Adafruit_RA8875(uint8_t CS, uint8_t RST) { + _cs = CS; + _rst = RST; +} + +boolean Adafruit_RA8875::begin(enum RA8875sizes s) { + _size = s; + + if (_size == RA8875_480x272) { + _width = 480; + _height = 272; + } + if (_size == RA8875_800x480) { + _width = 800; + _height = 480; + } + + pinMode(_cs, OUTPUT); + digitalWrite(_cs, HIGH); + pinMode(_rst, OUTPUT); + digitalWrite(_rst, LOW); + + digitalWrite(_rst, LOW); + delay(100); + digitalWrite(_rst, HIGH); + delay(100); + + SPI.begin(); + SPI.setClockDivider(SPI_CLOCK_DIV128); + SPI.setDataMode(SPI_MODE0); + + if (readReg(0) != 0x75) { + return false; + } + + initialize(); + + SPI.setClockDivider(SPI_CLOCK_DIV4); + + return true; +} + + +/************************* Initialization *********************************/ + +void Adafruit_RA8875::softReset(void) { + writeCommand(RA8875_PWRR); + writeData(RA8875_PWRR_SOFTRESET); + writeData(RA8875_PWRR_NORMAL); + delay(1); +} + +void Adafruit_RA8875::PLLinit(void) { +// for 480 x 272 + if (_size == RA8875_480x272) { + writeReg(RA8875_PLLC1, RA8875_PLLC1_PLLDIV1 + 10); + delay(1); + writeReg(RA8875_PLLC2, RA8875_PLLC2_DIV4); + delay(1); + } + if (_size == RA8875_800x480) { + writeReg(RA8875_PLLC1, RA8875_PLLC1_PLLDIV1 + 10); + delay(1); + writeReg(RA8875_PLLC2, RA8875_PLLC2_DIV4); + delay(1); + } +} + + +void Adafruit_RA8875::initialize(void) { + PLLinit(); + writeReg(RA8875_SYSR, RA8875_SYSR_16BPP | RA8875_SYSR_MCU8); + + // for 480 x 272 + uint8_t pixclk, hsync_start, hsync_pw, hsync_finetune, hsync_nondisp, vsync_pw; + uint16_t vsync_nondisp, vsync_start; + if (_size == RA8875_480x272) { + pixclk = RA8875_PCSR_PDATL | RA8875_PCSR_8CLK; + hsync_nondisp = 10; + hsync_start = 8; + hsync_pw = 48; + hsync_finetune = 0; + vsync_nondisp = 3; + vsync_start = 8; + vsync_pw = 10; + } else if (_size == RA8875_800x480) { + pixclk = RA8875_PCSR_PDATL | RA8875_PCSR_2CLK; + hsync_nondisp = 26; + hsync_start = 32; + hsync_pw = 96; + hsync_finetune = 0; + + vsync_nondisp = 32; + vsync_start = 23; + vsync_pw = 2; + } + + writeReg(RA8875_PCSR, pixclk); + delay(1); + // Horizontal settings registers + writeReg(RA8875_HDWR, (_width / 8) - 1); // H width: (HDWR + 1) * 8 = 480 + writeReg(RA8875_HNDFTR, RA8875_HNDFTR_DE_HIGH + hsync_finetune); + writeReg(RA8875_HNDR, (hsync_nondisp - hsync_finetune - 2)/8); // H non-display: HNDR * 8 + HNDFTR + 2 = 10 + writeReg(RA8875_HSTR, hsync_start/8 - 1); // Hsync start: (HSTR + 1)*8 + writeReg(RA8875_HPWR, RA8875_HPWR_LOW + (hsync_pw/8 - 1)); // HSync pulse width = (HPWR+1) * 8 + // Vertical settings registers + writeReg(RA8875_VDHR0, (uint16_t)(_height - 1) & 0xFF); + writeReg(RA8875_VDHR1, (uint16_t)(_height - 1) >> 8); + writeReg(RA8875_VNDR0, vsync_nondisp-1); // V non-display period = VNDR + 1 + writeReg(RA8875_VNDR1, vsync_nondisp >> 8); + writeReg(RA8875_VSTR0, vsync_start-1); // Vsync start position = VSTR + 1 + writeReg(RA8875_VSTR1, vsync_start >> 8); + writeReg(RA8875_VPWR, RA8875_VPWR_LOW + vsync_pw - 1); // Vsync pulse width = VPWR + 1 + + // Set active window X + writeReg(RA8875_HSAW0, 0); // horizontal start point + writeReg(RA8875_HSAW1, 0); + writeReg(RA8875_HEAW0, (uint16_t)(_width - 1) & 0xFF); // horizontal end point + writeReg(RA8875_HEAW1, (uint16_t)(_width - 1) >> 8); + + // Set active window Y + writeReg(RA8875_VSAW0, 0); // vertical start point + writeReg(RA8875_VSAW1, 0); + writeReg(RA8875_VEAW0, (uint16_t)(_height - 1) & 0xFF); // horizontal end point + writeReg(RA8875_VEAW1, (uint16_t)(_height - 1) >> 8); + + // touch panel? + + // clear full window + writeReg(RA8875_MCLR, RA8875_MCLR_START | RA8875_MCLR_FULL); + delay(500); +} + +uint16_t Adafruit_RA8875::width(void) { return _width; } +uint16_t Adafruit_RA8875::height(void) { return _height; } + + + +/************************* Graphics ***********************************/ + +void Adafruit_RA8875::pushPixels(uint32_t num, uint16_t p) { + digitalWrite(_cs, LOW); + SPI.transfer(RA8875_DATAWRITE); + while (num--) { + SPI.transfer(p >> 8); + SPI.transfer(p); + } + digitalWrite(_cs, HIGH); +} + +void Adafruit_RA8875::graphicsMode(void) { + writeCommand(RA8875_MWCR0); + uint8_t temp = readData(); + temp &= ~RA8875_MWCR0_TXTMODE; // bit #7 + writeData(temp); +} + +void Adafruit_RA8875::setXY(uint16_t x, uint16_t y) { + writeReg(RA8875_CURH0, x); + writeReg(RA8875_CURH1, x >> 8); + writeReg(RA8875_CURV0, y); + writeReg(RA8875_CURV1, y >> 8); +} + +void Adafruit_RA8875::fillRect(void) { + writeCommand(RA8875_DCR); + writeData(RA8875_DCR_LINESQUTRI_STOP | RA8875_DCR_DRAWSQUARE); + writeData(RA8875_DCR_LINESQUTRI_START | RA8875_DCR_FILL | RA8875_DCR_DRAWSQUARE); +} + +/************************* Mid Level ***********************************/ + +void Adafruit_RA8875::GPIOX(boolean on) { + if (on) + writeReg(RA8875_GPIOX, 1); + else + writeReg(RA8875_GPIOX, 0); +} + +void Adafruit_RA8875::PWM1out(uint8_t p) { + writeReg(RA8875_P1DCR, p); +} + +void Adafruit_RA8875::PWM2out(uint8_t p) { + writeReg(RA8875_P2DCR, p); +} + +void Adafruit_RA8875::PWM1config(boolean on, uint8_t clock) { + if (on) { + writeReg(RA8875_P1CR, RA8875_P1CR_ENABLE | (clock & 0xF)); + } else { + writeReg(RA8875_P1CR, RA8875_P1CR_DISABLE | (clock & 0xF)); + } +} + +void Adafruit_RA8875::PWM2config(boolean on, uint8_t clock) { + if (on) { + writeReg(RA8875_P2CR, RA8875_P2CR_ENABLE | (clock & 0xF)); + } else { + writeReg(RA8875_P2CR, RA8875_P2CR_DISABLE | (clock & 0xF)); + } +} + +void Adafruit_RA8875::touchEnable(boolean on) { + if (on) { + writeReg(RA8875_TPCR0, RA8875_TPCR0_ENABLE | RA8875_TPCR0_WAIT_4096CLK | + RA8875_TPCR0_WAKEDISABLE | RA8875_TPCR0_ADCCLK_DIV4); // 10mhz max! + writeReg(RA8875_TPCR1, RA8875_TPCR1_AUTO | RA8875_TPCR1_VREFEXT + | RA8875_TPCR1_DEBOUNCE); + writeReg(RA8875_INTC1, readReg(RA8875_INTC1) | RA8875_INTC1_TP); + } else { + writeReg(RA8875_INTC1, readReg(RA8875_INTC1) & ~RA8875_INTC1_TP); + writeReg(RA8875_TPCR0, RA8875_TPCR0_DISABLE); + } +} + +boolean Adafruit_RA8875::touched(void) { + if (readReg(RA8875_INTC2) & RA8875_INTC2_TP) return true; + return false; +} + +boolean Adafruit_RA8875::touchRead(uint16_t *x, uint16_t *y) { + uint16_t tx, ty; + uint8_t temp; + + writeCommand(RA8875_TPXH); + tx = readData(); + ty = readData(); + temp = readData(); + Serial.print("[0x"); + Serial.print(tx, HEX); Serial.print(", "); + Serial.print(ty, HEX); Serial.print(", "); + Serial.print(temp, HEX); Serial.println("]"); + + /* + tx = readReg(RA8875_TPXH); + ty = readReg(RA8875_TPYH); + temp = readReg(RA8875_TPXYL); + */ + tx <<= 2; + ty <<= 2; + tx |= temp & 0x03; // get the bottom x bits + ty |= (temp >> 2) & 0x03; // get the bottom y bits + + *x = tx; + *y = ty; + + writeReg(RA8875_INTC2, RA8875_INTC2_TP); + + return true; +} + +void Adafruit_RA8875::displayOn(boolean on) { + if (on) + writeReg(RA8875_PWRR, RA8875_PWRR_NORMAL | RA8875_PWRR_DISPON); + else + writeReg(RA8875_PWRR, RA8875_PWRR_NORMAL | RA8875_PWRR_DISPOFF); +} + +void Adafruit_RA8875::sleep(boolean sleep) { + if (sleep) + writeReg(RA8875_PWRR, RA8875_PWRR_DISPOFF | RA8875_PWRR_SLEEP); + else + writeReg(RA8875_PWRR, RA8875_PWRR_DISPOFF); +} + +/************************* Low Level ***********************************/ + +void Adafruit_RA8875::writeReg(uint8_t reg, uint8_t val) { + writeCommand(reg); + writeData(val); +} + +uint8_t Adafruit_RA8875::readReg(uint8_t reg) { + writeCommand(reg); + return readData(); +} + +void Adafruit_RA8875::writeData(uint8_t d) { + digitalWrite(_cs, LOW); + SPI.transfer(RA8875_DATAWRITE); + SPI.transfer(d); + digitalWrite(_cs, HIGH); + + Serial.print(" = 0x"); Serial.println(d, HEX); +} + +uint8_t Adafruit_RA8875::readData(void) { + digitalWrite(_cs, LOW); + SPI.transfer(RA8875_DATAREAD); + uint8_t x = SPI.transfer(0x0); + digitalWrite(_cs, HIGH); + return x; +} + +void Adafruit_RA8875::writeCommand(uint8_t d) { + //Serial.print("$"); Serial.print(d, HEX); + digitalWrite(_cs, LOW); + SPI.transfer(RA8875_CMDWRITE); + SPI.transfer(d); + digitalWrite(_cs, HIGH); +} + +uint8_t Adafruit_RA8875::readStatus(void) { + digitalWrite(_cs, LOW); + SPI.transfer(RA8875_CMDREAD); + uint8_t x = SPI.transfer(0x0); + digitalWrite(_cs, HIGH); + return x; +} diff --git a/Adafruit_RA8875.h b/Adafruit_RA8875.h new file mode 100644 index 0000000..a8ba415 --- /dev/null +++ b/Adafruit_RA8875.h @@ -0,0 +1,248 @@ +#include + +// Sizes! +enum RA8875sizes { RA8875_480x272, RA8875_800x480 }; + + + +class Adafruit_RA8875 { + public: + Adafruit_RA8875(uint8_t cs, uint8_t rst); + boolean begin(enum RA8875sizes s); + void softReset(void); + void displayOn(boolean on); + void sleep(boolean sleep); + + void pushPixels(uint32_t num, uint16_t p); + void graphicsMode(void); + void setXY(uint16_t x, uint16_t y); + void fillRect(void); + + void GPIOX(boolean on); + void PWM1config(boolean on, uint8_t clock); + void PWM2config(boolean on, uint8_t clock); + void PWM1out(uint8_t p); + void PWM2out(uint8_t p); + + void touchEnable(boolean on); + boolean touched(void); + boolean touchRead(uint16_t *x, uint16_t *y); + + void writeReg(uint8_t reg, uint8_t val); + uint8_t readReg(uint8_t reg); + void writeData(uint8_t d); + uint8_t readData(void); + void writeCommand(uint8_t d); + uint8_t readStatus(void); + + uint16_t width(void); + uint16_t height(void); + + private: + void PLLinit(void); + void initialize(void); + + uint8_t _cs, _rst; + uint16_t _width, _height; + enum RA8875sizes _size; +}; + + +// Colors! +#define RA8875_BLACK 0x0000 +#define RA8875_BLUE 0x001F +#define RA8875_RED 0xF800 +#define RA8875_GREEN 0x07E0 +#define RA8875_CYAN 0x07FF +#define RA8875_MAGENTA 0xF81F +#define RA8875_YELLOW 0xFFE0 +#define RA8875_WHITE 0xFFFF + +// Command/Data pins for SPI +#define RA8875_DATAWRITE 0x00 +#define RA8875_DATAREAD 0x40 +#define RA8875_CMDWRITE 0x80 +#define RA8875_CMDREAD 0xC0 + +// Registers & bits +#define RA8875_PWRR 0x01 +#define RA8875_PWRR_DISPON 0x80 +#define RA8875_PWRR_DISPOFF 0x00 +#define RA8875_PWRR_SLEEP 0x02 +#define RA8875_PWRR_NORMAL 0x00 +#define RA8875_PWRR_SOFTRESET 0x01 + +#define RA8875_MRWC 0x02 + +#define RA8875_GPIOX 0xC7 + +#define RA8875_PLLC1 0x88 +#define RA8875_PLLC1_PLLDIV2 0x80 +#define RA8875_PLLC1_PLLDIV1 0x00 + +#define RA8875_PLLC2 0x89 +#define RA8875_PLLC2_DIV1 0x00 +#define RA8875_PLLC2_DIV2 0x01 +#define RA8875_PLLC2_DIV4 0x02 +#define RA8875_PLLC2_DIV8 0x03 +#define RA8875_PLLC2_DIV16 0x04 +#define RA8875_PLLC2_DIV32 0x05 +#define RA8875_PLLC2_DIV64 0x06 +#define RA8875_PLLC2_DIV128 0x07 + +#define RA8875_SYSR 0x10 +#define RA8875_SYSR_8BPP 0x00 +#define RA8875_SYSR_16BPP 0x0C +#define RA8875_SYSR_MCU8 0x00 +#define RA8875_SYSR_MCU16 0x03 + +#define RA8875_PCSR 0x04 +#define RA8875_PCSR_PDATR 0x00 +#define RA8875_PCSR_PDATL 0x80 +#define RA8875_PCSR_CLK 0x00 +#define RA8875_PCSR_2CLK 0x01 +#define RA8875_PCSR_4CLK 0x02 +#define RA8875_PCSR_8CLK 0x03 + +#define RA8875_HDWR 0x14 + +#define RA8875_HNDFTR 0x15 +#define RA8875_HNDFTR_DE_HIGH 0x00 +#define RA8875_HNDFTR_DE_LOW 0x80 + +#define RA8875_HNDR 0x16 +#define RA8875_HSTR 0x17 +#define RA8875_HPWR 0x18 +#define RA8875_HPWR_LOW 0x00 +#define RA8875_HPWR_HIGH 0x80 + +#define RA8875_VDHR0 0x19 +#define RA8875_VDHR1 0x1A +#define RA8875_VNDR0 0x1B +#define RA8875_VNDR1 0x1C +#define RA8875_VSTR0 0x1D +#define RA8875_VSTR1 0x1E +#define RA8875_VPWR 0x1F +#define RA8875_VPWR_LOW 0x00 +#define RA8875_VPWR_HIGH 0x80 + +#define RA8875_HSAW0 0x30 +#define RA8875_HSAW1 0x31 +#define RA8875_VSAW0 0x32 +#define RA8875_VSAW1 0x33 + +#define RA8875_HEAW0 0x34 +#define RA8875_HEAW1 0x35 +#define RA8875_VEAW0 0x36 +#define RA8875_VEAW1 0x37 + +#define RA8875_MCLR 0x8E +#define RA8875_MCLR_START 0x80 +#define RA8875_MCLR_STOP 0x00 +#define RA8875_MCLR_READSTATUS 0x80 +#define RA8875_MCLR_FULL 0x00 +#define RA8875_MCLR_ACTIVE 0x40 + +#define RA8875_DCR 0x90 +#define RA8875_DCR_LINESQUTRI_START 0x80 +#define RA8875_DCR_LINESQUTRI_STOP 0x00 +#define RA8875_DCR_LINESQUTRI_STATUS 0x80 +#define RA8875_DCR_CIRCLE_START 0x40 +#define RA8875_DCR_CIRCLE_STATUS 0x40 +#define RA8875_DCR_CIRCLE_STOP 0x00 +#define RA8875_DCR_FILL 0x20 +#define RA8875_DCR_NOFILL 0x00 +#define RA8875_DCR_DRAWLINE 0x00 +#define RA8875_DCR_DRAWSQUARE 0x10 + +#define RA8875_MWCR0 0x40 +#define RA8875_MWCR0_GFXMODE 0x00 +#define RA8875_MWCR0_TXTMODE 0x80 + +#define RA8875_CURH0 0x46 +#define RA8875_CURH1 0x47 +#define RA8875_CURV0 0x48 +#define RA8875_CURV1 0x49 + +#define RA8875_P1CR 0x8A +#define RA8875_P1CR_ENABLE 0x80 +#define RA8875_P1CR_DISABLE 0x00 +#define RA8875_P1CR_CLKOUT 0x10 +#define RA8875_P1CR_PWMOUT 0x00 + +#define RA8875_P1DCR 0x8B + +#define RA8875_P2CR 0x8C +#define RA8875_P2CR_ENABLE 0x80 +#define RA8875_P2CR_DISABLE 0x00 +#define RA8875_P2CR_CLKOUT 0x10 +#define RA8875_P2CR_PWMOUT 0x00 + +#define RA8875_P2DCR 0x8D + +#define RA8875_PWM_CLK_DIV1 0x00 +#define RA8875_PWM_CLK_DIV2 0x01 +#define RA8875_PWM_CLK_DIV4 0x02 +#define RA8875_PWM_CLK_DIV8 0x03 +#define RA8875_PWM_CLK_DIV16 0x04 +#define RA8875_PWM_CLK_DIV32 0x05 +#define RA8875_PWM_CLK_DIV64 0x06 +#define RA8875_PWM_CLK_DIV128 0x07 +#define RA8875_PWM_CLK_DIV256 0x08 +#define RA8875_PWM_CLK_DIV512 0x09 +#define RA8875_PWM_CLK_DIV1024 0x0A +#define RA8875_PWM_CLK_DIV2048 0x0B +#define RA8875_PWM_CLK_DIV4096 0x0C +#define RA8875_PWM_CLK_DIV8192 0x0D +#define RA8875_PWM_CLK_DIV16384 0x0E +#define RA8875_PWM_CLK_DIV32768 0x0F + +#define RA8875_TPCR0 0x70 +#define RA8875_TPCR0_ENABLE 0x80 +#define RA8875_TPCR0_DISABLE 0x00 +#define RA8875_TPCR0_WAIT_512CLK 0x00 +#define RA8875_TPCR0_WAIT_1024CLK 0x10 +#define RA8875_TPCR0_WAIT_2048CLK 0x20 +#define RA8875_TPCR0_WAIT_4096CLK 0x30 +#define RA8875_TPCR0_WAIT_8192CLK 0x40 +#define RA8875_TPCR0_WAIT_16384CLK 0x50 +#define RA8875_TPCR0_WAIT_32768CLK 0x60 +#define RA8875_TPCR0_WAIT_65536CLK 0x70 +#define RA8875_TPCR0_WAKEENABLE 0x08 +#define RA8875_TPCR0_WAKEDISABLE 0x00 +#define RA8875_TPCR0_ADCCLK_DIV1 0x00 +#define RA8875_TPCR0_ADCCLK_DIV2 0x01 +#define RA8875_TPCR0_ADCCLK_DIV4 0x02 +#define RA8875_TPCR0_ADCCLK_DIV8 0x03 +#define RA8875_TPCR0_ADCCLK_DIV16 0x04 +#define RA8875_TPCR0_ADCCLK_DIV32 0x05 +#define RA8875_TPCR0_ADCCLK_DIV64 0x06 +#define RA8875_TPCR0_ADCCLK_DIV128 0x07 + +#define RA8875_TPCR1 0x71 +#define RA8875_TPCR1_AUTO 0x00 +#define RA8875_TPCR1_MANUAL 0x40 +#define RA8875_TPCR1_VREFINT 0x00 +#define RA8875_TPCR1_VREFEXT 0x20 +#define RA8875_TPCR1_DEBOUNCE 0x04 +#define RA8875_TPCR1_NODEBOUNCE 0x00 +#define RA8875_TPCR1_IDLE 0x00 +#define RA8875_TPCR1_WAIT 0x01 +#define RA8875_TPCR1_LATCHX 0x02 +#define RA8875_TPCR1_LATCHY 0x03 + +#define RA8875_TPXH 0x72 +#define RA8875_TPYH 0x73 +#define RA8875_TPXYL 0x74 + +#define RA8875_INTC1 0xF0 +#define RA8875_INTC1_KEY 0x10 +#define RA8875_INTC1_DMA 0x08 +#define RA8875_INTC1_TP 0x04 +#define RA8875_INTC1_BTE 0x02 + +#define RA8875_INTC2 0xF1 +#define RA8875_INTC2_KEY 0x10 +#define RA8875_INTC2_DMA 0x08 +#define RA8875_INTC2_TP 0x04 +#define RA8875_INTC2_BTE 0x02