Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

setRotation() not working with HX8340B (fix included) #1

Closed
Stephanie-Maks opened this Issue · 5 comments

3 participants

@Stephanie-Maks

The Adafruit_GFX function setRotation is not working with this library / with the 2.2" TFT display.

I have figured out what was required and have modified the library to incorporate the setRotation() functionality.

The two specific functions which needed to be changed were the ::drawPixel and the ::fillRect functions.

I've tested this with the example sketch for rotations 0, 1, 2, and 3.

Modified cpp file as follows:

/***************************************************
  This is a library for the Adafruit 2.2" SPI display.
  This library works with the Adafruit 2.2" TFT Breakout w/SD card
  ----> http://www.adafruit.com/products/797

  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 3 or 4 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include <SPI.h>

#include "Adafruit_GFX.h"
#include "Adafruit_HX8340B.h"

// use bitbang SPI (not suggested)
Adafruit_HX8340B::Adafruit_HX8340B(int8_t SID, int8_t SCLK, int8_t RST, int8_t CS) {
  sid = SID;
  sclk = SCLK;
  rst = RST;
  cs = CS;
  hwSPI = false;
}

// use hardware SPI
Adafruit_HX8340B::Adafruit_HX8340B(int8_t RST, int8_t CS) {
  sid = -1;
  sclk = -1;
  rst = RST;
  cs = CS;
  hwSPI = true;
}


void Adafruit_HX8340B::begin() {
  // Constructor for underlying GFX library
  constructor(HX8340B_LCDWIDTH, HX8340B_LCDHEIGHT);

  // set pin directions
  if (! hwSPI) {
    pinMode(sid, OUTPUT);
    pinMode(sclk, OUTPUT);
  }
  pinMode(rst, OUTPUT);
  pinMode(cs, OUTPUT);

  // Set pins low by default (except reset)
  if (! hwSPI) {
    digitalWrite(sid, LOW);
    digitalWrite(sclk, LOW);
  }
  digitalWrite(cs, LOW);
  digitalWrite(rst, HIGH);

  // Reset the LCD
  digitalWrite(rst, HIGH);
  delay(100);
  digitalWrite(rst, LOW);
  delay(50);
  digitalWrite(rst, HIGH);
  delay(50);


  csport    = portOutputRegister(digitalPinToPort(cs));
  cspinmask = digitalPinToBitMask(cs);

  if (! hwSPI) {
    clkport    = portOutputRegister(digitalPinToPort(sclk));
    clkpinmask = digitalPinToBitMask(sclk);
    dataport    = portOutputRegister(digitalPinToPort(sid));
    datapinmask = digitalPinToBitMask(sid);
  } else {
    clkport    = portOutputRegister(digitalPinToPort(13));
    clkpinmask = digitalPinToBitMask(13);
    dataport    = portOutputRegister(digitalPinToPort(11));
    datapinmask = digitalPinToBitMask(11);
    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV8); // 4 MHz (half speed)
    SPI.setBitOrder(MSBFIRST);
    SPI.setDataMode(SPI_MODE0);
    pinMode(13, OUTPUT);
    pinMode(11, OUTPUT);
  }

  *csport &= ~cspinmask;
  HX8340B_command(HX8340B_N_SETEXTCMD); 
  writeData(0xFF);
  writeData(0x83);
  writeData(0x40); 

  HX8340B_command(HX8340B_N_SPLOUT); 
  delay(100);

  HX8340B_command(0xCA);                  // Undocumented register?
  writeData(0x70);
  writeData(0x00);
  writeData(0xD9); 
  writeData(0x01);
  writeData(0x11); 

  HX8340B_command(0xC9);                  // Undocumented register?
  writeData(0x90);
  writeData(0x49);
  writeData(0x10); 
  writeData(0x28);
  writeData(0x28); 
  writeData(0x10); 
  writeData(0x00); 
  writeData(0x06);
  delay(20);

  HX8340B_command(HX8340B_N_SETGAMMAP);
  writeData(0x60);
  writeData(0x71);
  writeData(0x01); 
  writeData(0x0E);
  writeData(0x05); 
  writeData(0x02); 
  writeData(0x09); 
  writeData(0x31);
  writeData(0x0A);

  HX8340B_command(HX8340B_N_SETGAMMAN); 
  writeData(0x67);
  writeData(0x30);
  writeData(0x61); 
  writeData(0x17);
  writeData(0x48); 
  writeData(0x07); 
  writeData(0x05); 
  writeData(0x33); 
  delay(10);

  HX8340B_command(HX8340B_N_SETPWCTR5); 
  writeData(0x35);
  writeData(0x20);
  writeData(0x45); 

  HX8340B_command(HX8340B_N_SETPWCTR4); 
  writeData(0x33);
  writeData(0x25);
  writeData(0x4c); 
  delay(10);

  HX8340B_command(HX8340B_N_COLMOD);  // Color Mode
  writeData(0x05);                 // 0x05 = 16bpp, 0x06 = 18bpp

  HX8340B_command(HX8340B_N_DISPON); 
  delay(10);

  HX8340B_command(HX8340B_N_CASET); 
  writeData(0x00);
  writeData(0x00);
  writeData(0x00); 
  writeData(0xaf);                 // 175

  HX8340B_command(HX8340B_N_PASET); 
  writeData(0x00);
  writeData(0x00);
  writeData(0x00); 
  writeData(0xdb);                 // 219

  HX8340B_command(HX8340B_N_RAMWR);

  *csport |=  cspinmask;
  //clearDisplay();
}

// clear everything
void Adafruit_HX8340B::fillDisplay(uint16_t c) {
  fillRect(0, 0, HX8340B_LCDWIDTH, HX8340B_LCDHEIGHT, c);
/*
  setWindow(0, 0, HX8340B_LCDWIDTH-1, HX8340B_LCDHEIGHT-1);
  *csport &= ~cspinmask;
  uint32_t i = HX8340B_LCDWIDTH;
  i *= HX8340B_LCDHEIGHT;
  while (i--) {
    writeData((c>>8) & 0xFF);
    writeData(c & 0xFF);
  }
  *csport |=  cspinmask;
*/
}

void Adafruit_HX8340B::invertDisplay(uint8_t i) {
}

void Adafruit_HX8340B::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
  // check rotation, move pixel around if necessary
  switch (getRotation()) {
  case 1:
    swap(x, y);
    swap(h, w);
    x = WIDTH - x - w;
    break;
  case 2:
    x = WIDTH - x - w;
    y = HEIGHT - y - h;
    break;
  case 3:
    swap(x, y);
    swap(h, w);
    y = HEIGHT - y - h;
    break;
  }  
  setWindow(x, y, x+w-1, y+h-1);
  *csport &= ~cspinmask;
  uint32_t i = w;
  i *= h;
  while (i--) {
    writeData((color>>8) & 0xFF);
    writeData(color & 0xFF);
  }
  *csport |=  cspinmask;
}

void Adafruit_HX8340B::pushColor(uint16_t color) {
  *csport &= ~cspinmask;
  writeData((color>>8) & 0xFF);
  writeData(color & 0xFF);
  *csport |=  cspinmask;
}

// the most basic function, set a single pixel
void Adafruit_HX8340B::drawPixel(int16_t x, int16_t y, uint16_t color) {
  if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
    return;

  // check rotation, move pixel around if necessary
  switch (getRotation()) {
  case 1:
    swap(x, y);
    x = WIDTH - x - 1;
    break;
  case 2:
    x = WIDTH - x - 1;
    y = HEIGHT - y - 1;
    break;
  case 3:
    swap(x, y);
    y = HEIGHT - y - 1;
    break;
  }  

  setWindow(x, y, x+1, y+1);
  *csport &= ~cspinmask;
  writeData((color>>8) & 0xFF);
  writeData(color & 0xFF);
  *csport |=  cspinmask;

}


void Adafruit_HX8340B::HX8340B_command(uint8_t c) { 
  // Prepend leading bit instead of D/C pin

  if (hwSPI) {
    uint8_t saved_spimode = SPCR;
    SPCR = 0;

#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined (__AVR_ATmega328__) || defined(__AVR_ATmega8__)
    PORTB &= ~_BV(3);  // PB3 = MOSI
    PORTB |= _BV(5);  // PB5 = SCLK
    PORTB &= ~_BV(5);
    // also do mega next eh?
#else
    *dataport &=  ~datapinmask;
    *clkport |=  clkpinmask;
    *clkport &= ~clkpinmask;
#endif

    SPCR = saved_spimode;

    SPDR = c;
    while(!(SPSR & _BV(SPIF)));
  } else {
    *dataport &=  ~datapinmask;
    *clkport |=  clkpinmask;
    *clkport &= ~clkpinmask;
    for(uint8_t bit = 0x80; bit; bit >>= 1) {
      if(c & bit) *dataport |=  datapinmask;
      else        *dataport &= ~datapinmask;
      *clkport |=  clkpinmask;
      *clkport &= ~clkpinmask;
    }
  }
}


void Adafruit_HX8340B::writeData(uint8_t c) {
  // Prepend leading bit instead of D/C pin
  if (hwSPI) {
    uint8_t saved_spimode = SPCR;
    SPCR = 0;
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined (__AVR_ATmega328__) || defined(__AVR_ATmega8__)
    PORTB |= _BV(3);  // PB3 = MOSI
    PORTB |= _BV(5);  // PB5 = SCLK
    PORTB &= ~_BV(5);
    // also do mega next eh?
#else
    *dataport |=  datapinmask;
    *clkport |=  clkpinmask;
    *clkport &= ~clkpinmask;
#endif
    SPCR = saved_spimode;
    SPDR = c;
    while(!(SPSR & _BV(SPIF)));
  } else {
    *dataport |=  datapinmask;
    *clkport |=  clkpinmask;
    *clkport &= ~clkpinmask;
    for(uint8_t bit = 0x80; bit; bit >>= 1) {
      if(c & bit) *dataport |=  datapinmask;
      else        *dataport &= ~datapinmask;
      *clkport |=  clkpinmask;
      *clkport &= ~clkpinmask;
    }
  }
}

void Adafruit_HX8340B::writereg(uint8_t reg, uint8_t value) { 
  *csport &= ~cspinmask;
  HX8340B_command(reg);
  HX8340B_command(value);
  *csport |=  cspinmask;
}

void Adafruit_HX8340B::setWindow(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1)
{
  *csport &= ~cspinmask;
  HX8340B_command(HX8340B_N_CASET);
  writeData(x0>>8);
  writeData(x0);
  writeData(x1>>8);
  writeData(x1);

  HX8340B_command(HX8340B_N_PASET);
  writeData(y0>>8);
  writeData(y0);
  writeData(y1>>8);
  writeData(y1);

  HX8340B_command(HX8340B_N_RAMWR);
  *csport |=  cspinmask;
}

uint16_t Adafruit_HX8340B::Color565(uint8_t r, uint8_t g, uint8_t b) {
  uint16_t c;
  c = r >> 3;
  c <<= 6;
  c |= g >> 2;
  c <<= 5;
  c |= b >> 3;

  return c;
}
@rmm200

Be careful to not regress the Mega 2560 fix - replace 11 and 13 with the appropriate symbolics from Arduino_pinouts.h.

@PaintYourDragon

Thanks for the fix, Stephanie. I ended up implementing it at a slightly deeper level. if you download the latest, you might see a little performance boost in places. Let me know if this all works for you, and if so, I'll mark the issue closed. Thanks!

@Stephanie-Maks

I just tried it out and it works great. I see you moved the rotation code to the setWindow function so it only had to be implemented a single time, I missed that. :)

It runs great for me with both the example sketch and my own project.

Thanks very much!

@rmm200

I confirm the new submitted version works correctly with the Mega 2560, with both the functional test example and the rose display example and hardware SPI. Thank you Stephanie and Adafruit! Loving the display!

@PaintYourDragon

Woot! Thank you, fixers and testers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.