본문 바로가기

프로젝트/TFT LCD 한글 출력 (아두이노)

Hangul_SD,H ( SD카드에 폰트화일,인덱스화일 )

아두이노 Mega  사용시 주의할 점                                                                           

SD카드를 사용 하려면 Uno와 SPI핀 번호가 달라 다음 2가지 중

하나의 방법으로 해야 한다.

쉴드를 아두이노 Mega에서 SD카드 사용을 위한 방법(Uno와 SPI핀  다름)
Uno의 SPI핀번호에 해당하는 핀을  SPI핀과 연결함 번거롭다(납땜이 필요)  핀4개 사용불가
SD모듈을 따로 구입하여 사용한다. 얼마 안함 저렴함.( 추천 )

폰트화일과 인덱스파일은 스스로 만들어 보세요.  규격은 여기로                                   대부분의 경우 따로 폰트가 필요 없는 Hangul_Direct.H를                                              Mega보드(120자 정도)와 같이 사용 하면 됩니다.

 

HanGul.SD    ver 1.0  
 
//        HanGul.SD    ver 1.0     아두이노용 한글 출력 클래스
//
//        제작자  :  신 옥 진
//          
//        재배포 금지 링크를 사용 하세요.
//
//   Index1 구조 ( 4 Byte Record )  [폰트offset : 4byte Long]    
//   Index2 구조 ( 8 Byte Record )  [폰트코드 : 4byte Long][폰트offset : 4byte Long]  
//
//   Index2 사용시 소스코드에 #define _INDEX_2_ 코드 넣어야 함
//
//   < 소스 코드 순서 >
//   #define   _TFTLCD_      myLcd              // myLcd는 원하는 이름으로 하고 include 앞에 선언
//   #define _INDEX_TYPE_2_                     // 인덱스방법 2로 사용시에 만  (없을시 방법1)                                      
//   #include "c:\\Arduino\\HanGul_TFT.H"       // 헤더파일 전체 경로                                        
//   HanGul_TFT  ht;                            // 한글출력 클래스
//
//   폰트파일과 인덱스파일은 SD카드 "UTF_8//" 에 있는 것으로 함
//   바꿀려면  아래 define 부분을 수정하면 됨 (주의) 디렉토리 표시가 윈도우와 다름 '\'아니고  '/'사용                          

#ifndef _Hangul_TFT_          
#define _Hangul_TFT_      

#ifdef _INDEX_2_
#define _INDEX_FILE_ "UTF_8//fIndex2.idx"  //  인덱스2 파일
#else
#define _INDEX_FILE_ "UTF_8//fIndex1.idx"  //  인댁스1 파일
#endif
#define _FONT_FILE_  "UTF_8//Hangul.utf"   //  폰트 파일

                           
#include <SPI.h>              
#include <SD.h>                
#include <Adafruit_GFX.h>                                          
#include <UTFTGLUE.h>

#ifndef _MY_COLOR_               //  Color 정의
#define _MY_COLOR_
#define cBlack        0x0000
#define cWhite        0xFFFF
#define cRed          0xF800      
#define cGreen        0x0400
#define cBlue         0x001F
#define cSilver       0xC618
#define cGray         0x8410
#define cMaroon       0x8000
#define cYellow       0xFFE0
#define cOlive        0x8400
#define cLime         0x07E0
#define cAqua         0x07FF
#define cTeal         0x0410
#define cNavy         0x0010
#define cFuchsia      0xF81F
#define cPurple       0x8010
#define cTransparent  0xFFFFFFFF
#endif


UTFTGLUE  _TFTLCD_(0x9488,A2,A1,A3,A4,A0);  

#define  BASE_CODE  0xE28A82

String readLine(    File  inf  )
{
  char buff[50];
  int idx=0;
 
  while(true)
  {
     byte b,b2;

         b=inf.read();        
        if( b == 0x0d )
        {
            b2=  inf.read();          
            if( b2 == 0x0a )
            {            
               buff[idx]= 0;
               return( String( buff ) );
            }
            buff[idx++] = b;
            buff[idx++] = b2;
        }
        else buff[idx++] =b;        
  }
}

struct Box               // 문자열의 사각형 좌표
{
   int x,y,x2,y2;  
} ;

class HanGul_TFT
{
  private:
      unsigned short _HANGUL_FONT[16];               // 폰트 저장변수
      File _Index_File_,_Font_File_;       // 인덱스파일 , 폰트파일            
      int  _color=cWhite;                  // 폰트색상
      int  _bkColor = cBlack;              // 폰트배경색      

  public:  
      Box  box;    
   
    void start();                   // 한글클래스 시작
    void end();                     // 한글클래스 종료  : 사용 안해도 됨
    void color(int _c ) ;           // 글자색
    void color(int _c ,int _bk);    // 글자색,  배경색
    void fill(int _c);              // 바로 앞에 출력한 문자열을 _c 색으로 채우기
    void fill() ;                   // 배경색으로 채우기
    void rect(int _c);              // 바로 앞에 출력한 문자열에 _c 색으로 테두리 그리기
    void rect();                    // 문자색으로 테두리 그리기
    void under(int _c);             // 바로 앞에 출력한 문자열에 문자색으로 밑줄 그리기
    void under();                   // 문자색으로 밑줄 그리기
    void print( String s, int x, int y , int mx, int my );  // x,y좌표에 가로 mx배 ,세로 my배로 문장 출력
    void print( String s,int  x, int y  );                  //  1배
    void print( String s,int  x, int y ,int m  );           //  m배
   
  private:
    void _setDot_Func( int col, int row, int x, int y,int mx,int my ,int c );  //폰트의 1bit에 해당하는 점 그리기
    void _drawFont_Func( int x, int y,  int mx , int my);    
    #ifdef _INDEX_2_
    void getFont( long code );
    #endif    
};


void HanGul_TFT::start()
{
    #ifdef _Mega_
    SD.begin(53);    // mega
    #else
    SD.begin(10);    //  uno
    #endif
    pinMode(A0, OUTPUT);                  
    digitalWrite(A0, HIGH);               //  TFT LCD 시작  

    HanGul_TFT::_Index_File_ = SD.open(_INDEX_FILE_);   // 인덱스 파일 오픈  
    HanGul_TFT::_Font_File_  = SD.open(_FONT_FILE_);   // 폰트   파일 오픈      
}

void HanGul_TFT::end()         //   사용 안해도 됨
{
    _Index_File_.close();
    _Font_File_.close();
}  

void HanGul_TFT::color(int _c )
{
  _color=_c;    
}

void HanGul_TFT::color(int _c ,int _bk)
{
  _color=_c;
  _bkColor=_bk;

}

void HanGul_TFT::fill(int _c)                 // 문자열을  _c색상으로 채우기
{
    _TFTLCD_.setColor( _c  );    
    _TFTLCD_.fillRect(box.x,box.y,box.x2,box.y2);    

}

void HanGul_TFT::fill() { fill(_bkColor); }   // 문자열을  배경색상으로 채우기  // 문자열 지우기에 이용

void HanGul_TFT::rect(int _c)                 // _c색상으로 문자열의 외곽선 그리기
{
    _TFTLCD_.setColor( _c );
    _TFTLCD_.drawRect(box.x,box.y,box.x2,box.y2);    
}

void HanGul_TFT::rect() { rect(_color); }       // 문자색상으로 문자열의 외곽선 그리기

void HanGul_TFT::under(int _c)                  // 문자열에 _c색상으로 밑줄
{
    _TFTLCD_.setColor( _c );
    _TFTLCD_.fillRect(box.x, box.y2-2,box.x2,box.y2+1);    
}
void HanGul_TFT::under(){ under(_color); }                               // 문자열에 문자색상으로 밑줄

void HanGul_TFT::print( String s,int  x, int y  ) {  print( s, x, y , 1 ,1 ); }

void HanGul_TFT::print( String s,int  x, int y ,int m  ) { print( s, x, y , m, m  );  }



void HanGul_TFT::_setDot_Func( int col, int row, int x, int y,int mx,int my ,int c )
{                      
    _TFTLCD_.setColor( c );  
    for(int dx=0 ; dx< mx ;dx++)      
       for( int dy=0;dy<my;dy++)  
          _TFTLCD_.drawPixel(   x+col*mx+dx   ,y+row*my+dy  );  
}

void HanGul_TFT::_drawFont_Func( int x, int y,  int mx , int my)
{                                   // 문자(1자) 그리기
   
    for( int row=0; row< 16 ; row++)    // 폰트 bit 세로방향
    {
          for(int col=0;col<16;col++)      // 폰트 bit 가로방향
          {                                    
                if( _HANGUL_FONT[row] & 0b1000000000000000 )   _setDot_Func(  col,  row, x, y, mx, my, _color);
                else      _setDot_Func(  col,  row, x, y, mx, my, _bkColor  );        
                _HANGUL_FONT[row] <<= 1;                    // bit가 1이면 점그리기 함수 호출
          }
    }
}


#ifdef _INDEX_2_    //  Index 방법 2번이면
void HanGul_TFT::getFont( long code )
{
    long low=0, high = 11746;
    long now = 5873;
    long hCode,hIdx;
    long temp=-1;

    while(true)
    {
        _Index_File_.seek(now*8);
        _Index_File_.read(&hCode,4);     // 한글코드 읽기      
        if( hCode == code )
        {
        _Index_File_.seek(now*8+4);
        _Index_File_.read(&hIdx,4);
        _Font_File_.seek(hIdx);
        _Font_File_.read(_HANGUL_FONT ,32);
        return;
        }
    else if( hCode > code ) high = now;
    else  low = now;          
    now=(low+high)/2;
    if( now==temp) return;
    else temp=now;
    }  
}
#endif


void HanGul_TFT::print( String s, int x, int y , int mx, int my )
{  
    box.x=x;
    box.y=y;
    box.y2=y+16*my-1;    

    _TFTLCD_.setTextSize(my*2);            

    for( int p=0; p <s.length() ;p++)
    {                                                
        if(  isAscii(s[p])  )
        {      
            if( s[p]==0x0d )break;                                        
            _TFTLCD_.setCursor(x,y);  
            _TFTLCD_.setTextColor(_color,_bkColor);                                                                                                    
            _TFTLCD_.println(s[p]);          
            if( s[p]==0x20 ) x+=8*my;
            else x+=12*my;        
        }
        else
        {    
            _TFTLCD_.setColor( _color)  ;
           
                  long code =byte(s[p]);              
                  code = code << 8;
                  code+=byte(s[p+1]);              
                  code = code << 8;
                  code+=byte(s[p+2]);  
                  #ifdef _INDEX_2_
                   getFont(code);    
                  #else
                   code-= BASE_CODE;                
                   _Index_File_.seek(code*4);

                   long fPoint;
                   _Index_File_.read( &fPoint,4);

                   _Font_File_.seek( fPoint);
                   _Font_File_.read( _HANGUL_FONT ,32);    
                  #endif            
                  _drawFont_Func( x,  y, mx, my) ;
                  x+=16*mx;
                  p+=2;
                                 
         } // isASCII else
    }// p 스트링 길이 반복  
    box.x2=x-1;
}

/*
void HanGul_TFT::print( String s, int x, int y , int mx, int my )
{                        // 문자열을 그리는 함수
    box.x=x;                    
    box.y=y;    // 문자열 상자박스 좌표
    box.y2=y+16*my-1;    

    _TFTLCD_.setTextSize(my*2);  //  TFT LCD 내장 폰트 사이즈 설정          

    for( int p=0; p <s.length() ;p++) //문자열 가로방향으로 진행
    {                                                
        if(  isAscii(s[p])  )       // 문자가 아스키코드(내장폰트)
        {      
              if( s[p]==0x0d )break;    // 문자열 끝이면 빠져 나감                                    
              _TFTLCD_.setCursor(x,y);  
              _TFTLCD_.setTextColor(_color,_bkColor); // 내장폰트 색깔                                                                                                    
              _TFTLCD_.println(s[p]);          
              if( s[p]==0x20 ) x+=8*my; //공백은 가로로 8dot 이동  
              else x+=12*my;            //가로로 16Dot 이동
        }
        else
        {    
                     _TFTLCD_.setColor( _color)  ;
                    long code =byte(s[p]);      // 3Byte 문자(UTF-8)      
                    code = code << 8;    // 상위 Byte에서 하위byte로 읽어오기  
                    code+=byte(s[p+1]);              
                    code = code << 8;
                    code+=byte(s[p+2]);  
                   
                            code-= BASE_CODE;                
                            _Index_File_.seek(code*4);

                            long fPoint;
                            _Index_File_.read( &fPoint,4);

                            _Font_File_.seek( fPoint);
                            _Font_File_.read( _HANGUL_FONT ,32);  
                    //}
                    _drawFont_Func( x,  y, mx, my) ;
                    x+=16*mx;
                    p+=2;
                                 
        } // isASCII else
}// p 스트링 길이 반복  
box.x2=x-1;
} */

#endif
Hangul_SD.ino
  #define   _TFTLCD_      myLcd              // TFT LCD 이름 정의/
#define _INDEX_2_                   // 인덱스방법 2로 사용시     
// #define _Mega_                       // Mega 사용시  
#include  "D:\\Program Files (x86)\\Arduino\\myHeader\\HanGul_SD.H"                                                                          
                                         
HanGul_TFT  ht;     // 한글출력 클래스

void setup()
{      
  Serial.begin(9600);
  unsigned long startTime=millis();
  Serial.println(startTime);  
  ht.start();       
                                      
  myLcd.InitLCD();            
  myLcd.setRotation(3);   //3 가로 480x320  //2 세로   320x480
  myLcd.clrScr();     
  
  ht.color(cWhite,cBlack);          
  ht.print(F("┏┓┛┗┣┳┫┻╋┠┯"),5,0);      
  ht.color(cWhite,cRed);
  ht.print(F("★○●◎◇◆"),5,20,2);   
  ht.color(cRed,cBlack);
  ht.print(F("한글 English ☏☎ 123"),5,60,2,1);  
  ht.rect(cRed);         
  ht.color(cBlack,cYellow); 
  ht.print(F("English ☏☎ 123"),5,80);
  ht.color(cWhite,cBlack);
  
  #ifdef _INDEX_2_  
  ht.print(F("인 덱 스 방 법 2"),5,120,1,2); 
  #else
  ht.print(F("인 덱 스 방 법 1"),5,120,1,2);
  #endif
  
  ht.color(cRed);
  ht.print(F(" ☏☎ 123"),ht.box.x2,120,1,2); 
  ht.color(cBlue,cBlack);
  ht.rect(cRed);
  ht.print(F("한글 Eng ☏☎ 13"),5,180,3,1); 
  ht.color(cYellow,cRed);
  ht.print(F("한글출력 Demo"),5,210,2);  
  ht.color(cWhite,cBlack);
  ht.print(F("가로 세로 따로 조절 가능"),5,250,2);
  ht.under(cRed);   

  ht.print(F("보다 빠른 속도 개선Speed"),5,290,2);  
    
  unsigned long endTime=millis();
  Serial.println(endTime);  
  Serial.println(endTime-startTime);
  
}

void loop()
{
 
}