[HoloEye] 06_IPS TFT LCD MIRROR 모드

06_IPS_MIRROR기능

enter image description here

[HoloEye] 06_IPS TFT LCD MIRROR 모드

1. TFT_eSPI.h 라이브러리

이전부터 한창 활용했던 TFT_eSPI.h 라이브러리를 사용하는데 LCD 라이브러리들에 흔하디 흔한 MIRROR 또는 FLIP 함수가 없는 것이 아닌가!? 한참 찾고 검색했는데 혹시나 아시는 분 있으면 리플 부탁 드립니다. (–)(__)

그래서 이게 없을리가 없는데 없는데 하면서 라이브러리 코드까지 싹다 뒤졌는데 진짜 구현을 안해놨다.
쿨럭…
어쩔 수 없이 현재 사용하고 있는 TFT LCD 240x240 ST7789 드라이버의 데이터시트를 보고 기능을 직접 추가하기로 했다.

3시간 정도 검색하다가 라이브러리까지 싹 뒤진 것 같은데 진짜 없을 줄이야…

2. ST7789 데이터시트

https://www.rhydolabz.com/documents/33/ST7789.pdf
https://www.waveshare.com/w/upload/a/ae/ST7789_Datasheet.pdf

위 링크의 ST7789 데이터시트를 보면 DDRAM을 통해서 MIRROR 기능을 제공하고 있는데 레지스터 이름이 MADCTR 이다. (MAD가 들어가서 그런가 왠지 친근…)

enter image description here

MADCTR 레지스터 Parameter MV, MX, MY에 따라서 회전과 미러를 동시에 적용할 수 있다.
다행이 레지스터들은 코드상 #Define 을 잘해놨음

3. ST7789_Rotation.h

라이브러리에서 ST7789_Rotation.h 파일을 수정하면 된다.
참조경로는 아두이노 라이브리에 있다.

\Arduino\libraries\TFT_eSPI\TFT_Drivers

기존에 회전에 관련된 함수가 있는데 아두이노에서 다음과 같이 사용된다.

// TFT Setting
TFT_eSPI tft = TFT_eSPI();

tft.setRotation(0); // 0-3

이게 웃긴게 LCD 회전동작 4방향만 구현되어 있다. 때문에 입력파라메터가 0,1,2,3 까지만 가능하다.
여기에 MIRROR 기능을 추가하여 4,5,6,7 기능을 추가했다.
터치까지 offset 조절해서 구현하는 건 제외했다.(현재 만들고 있는 holo weather에는 필요 없음)

ST7789_Rotation.h 전체 코드

  // This is the command sequence that rotates the ST7789 driver coordinate frame

  writecommand(TFT_MADCTL);
  rotation = m % 8;
  switch (rotation) {
    case 0: // Portrait
#ifdef CGRAM_OFFSET
      if (_init_width == 135)
      {
        colstart = 52;
        rowstart = 40;
      }
      else if(_init_height == 280)
      {
        colstart = 0;
        rowstart = 20;
      }
      else if(_init_width == 172)
      {
        colstart = 34;
        rowstart = 0;
      }
      else if(_init_width == 170)
      {
        colstart = 35;
        rowstart = 0;
      }
      else
      {
        colstart = 0;
        rowstart = 0;
      }
#endif
      writedata(TFT_MAD_COLOR_ORDER);

      _width  = _init_width;
      _height = _init_height;
      break;

    case 1: // Landscape (Portrait + 90)
#ifdef CGRAM_OFFSET
      if (_init_width == 135)
      {
        colstart = 40;
        rowstart = 53;
      }
      else if(_init_height == 280)
      {
        colstart = 20;
        rowstart = 0;
      }
      else if(_init_width == 172)
      {
        colstart = 0;
        rowstart = 34;
      }
      else if(_init_width == 170)
      {
        colstart = 0;
        rowstart = 35;
      }
      else
      {
        colstart = 0;
        rowstart = 0;
      }
#endif
      writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);

      _width  = _init_height;
      _height = _init_width;
      break;

      case 2: // Inverter portrait
#ifdef CGRAM_OFFSET
      if (_init_width == 135)
      {
        colstart = 53;
        rowstart = 40;
      }
      else if(_init_height == 280)
      {
        colstart = 0;
        rowstart = 20;
      }
      else if(_init_width == 172)
      {
        colstart = 34;
        rowstart = 0;
      }
      else if(_init_width == 170)
      {
        colstart = 35;
        rowstart = 0;
      }
      else
      {
        colstart = 0;
        rowstart = 80;
      }
#endif
      writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);

      _width  = _init_width;
      _height = _init_height;
       break;
    case 3: // Inverted landscape
#ifdef CGRAM_OFFSET
      if (_init_width == 135)
      {
        colstart = 40;
        rowstart = 52;
      }
      else if(_init_height == 280)
      {
        colstart = 20;
        rowstart = 0;
      }
      else if(_init_width == 172)
      {
        colstart = 0;
        rowstart = 34;
      }
      else if(_init_width == 170)
      {
        colstart = 0;
        rowstart = 35;
      }
      else
      {
        colstart = 80;
        rowstart = 0;
      }
#endif
      writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);

      _width  = _init_height;
      _height = _init_width;
      break;
    case 4:
#ifdef CGRAM_OFFSET
      if (_init_width == 135)
      {
        colstart = 52;
        rowstart = 40;
      }
      else if(_init_height == 280)
      {
        colstart = 0;
        rowstart = 20;
      }
      else if(_init_width == 172)
      {
        colstart = 34;
        rowstart = 0;
      }
      else if(_init_width == 170)
      {
        colstart = 35;
        rowstart = 0;
      }
      else
      {
        colstart = 0;
        rowstart = 0;
      }
#endif
      writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER);

      _width  = _init_width;
      _height = _init_height;
      break;
    case 5:
#ifdef CGRAM_OFFSET
      if (_init_width == 135)
      {
        colstart = 40;
        rowstart = 53;
      }
      else if(_init_height == 280)
      {
        colstart = 20;
        rowstart = 0;
      }
      else if(_init_width == 172)
      {
        colstart = 0;
        rowstart = 34;
      }
      else if(_init_width == 170)
      {
        colstart = 0;
        rowstart = 35;
      }
      else
      {
        colstart = 80;
        rowstart = 0;
      }
#endif
      writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);

      _width  = _init_height;
      _height = _init_width;
      break;
    case 6:
#ifdef CGRAM_OFFSET
      if (_init_width == 135)
      {
        colstart = 53;
        rowstart = 40;
      }
      else if(_init_height == 280)
      {
        colstart = 0;
        rowstart = 20;
      }
      else if(_init_width == 172)
      {
        colstart = 34;
        rowstart = 0;
      }
      else if(_init_width == 170)
      {
        colstart = 35;
        rowstart = 0;
      }
      else
      {
        colstart = 0;
        rowstart = 80;
      }
#endif
      writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER);

      _width  = _init_width;
      _height = _init_height;
       break;
    case 7:
#ifdef CGRAM_OFFSET
      if (_init_width == 135)
      {
        colstart = 40;
        rowstart = 52;
      }
      else if(_init_height == 280)
      {
        colstart = 20;
        rowstart = 0;
      }
      else if(_init_width == 172)
      {
        colstart = 0;
        rowstart = 34;
      }
      else if(_init_width == 170)
      {
        colstart = 0;
        rowstart = 35;
      }
      else
      {
        colstart = 0;
        rowstart = 0;
      }
#endif
      writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER);

      _width  = _init_height;
      _height = _init_width;
      break;
  }

기존에서 수정된 부분만 간단히 보면

  1. 회전방향이 0-3에서 0-7로 늘어났으므로 %3 에서 %7로 변경
rotation = m % 8;
  1. MIRROR 가 적용된 각 회전방향에 따른 case 문 추가
    case 4:
      writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER);

      _width  = _init_width;
      _height = _init_height;
      break;
    case 5:
      writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);

      _width  = _init_height;
      _height = _init_width;
      break;
    case 6:
      writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER);

      _width  = _init_width;
      _height = _init_height;
       break;
    case 7:
      writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER);

      _width  = _init_height;
      _height = _init_width;
      break;
  1. MIRROR 적용으로 case 5, case 7 offset 변경
    case 5:
      else
      {
        colstart = 80;
        rowstart = 0;
      }

case 7:

      else
      {
        colstart = 0;
        rowstart = 0;
      }

찾는게 어려웠지 코드 수정은 쏘 심플!!

다시 빌드해서 동작시켰는데 잘 된다

현재 실시간 날씨 현황을 홀로큐브로 동작시켜서 뿌려줄려고 만들고 있는데 완성되면 간단히 공유해보겠다.

끝 :)

도움이 되셨다면 더 좋은 정보 공유를 위해 광고 클릭 부탁 드립니다 :)

댓글 쓰기

0 댓글