티스토리 뷰

OS/micro:bit

micro:bit 지니어스키트 : 한글출력

파란크리스마스 2019. 8. 31. 22:15
728x90

출처

micro:bit 지니어스키트 : 한글출력

전체소스 : source.zip

마이크로비트 지니어스키트의 LCD에 한글을 출력해보았습니다. 

블럭코딩에서 사용가능 하도록 확장라이브러리로 개발을 시도 했었지만, 블럭 코딩에 한글 문자열을 확장라이브러리에 전달 할 수 있는 방법을 알 수 없어서 확장라이브러리 개발은 포기하고, C++로 개발한 소스를 공개합니다. 

중국의 어떤 개발자도 한자 자체를 소리나는 대로 영문으로 전달하면 다시 한자로 변환해서 한자를 출력했는데, 한글을 소리나는 대로 영문으로 전달해서 해볼까 했지만, 굳이 필요로 할지 모르겠고, 개발 기간도 늘어나 구현은 나중으로 미루어 두었습니다.

전체적인 소스는 네이버카페( 블루투스 에서 한글전송하여 OLED에 보여주기.. : 네이버 카페 (아두이노 스토리) )에 공개된 소스를 기본으로 작성되었고, 소스 전체를 공개 했으니 다운 받아서 참고 하시면 됩니다.

main.cpp 소스

#include <MicroBit.h>
#include <mbed/pgmspace.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include "ASCFont.h"
#include "KSFont.h"

#define BLACK       0x0000

void matrixPrint(int XPOS,int YPOS,char *pChar);
byte *getHAN_font(byte HAN1, byte HAN2, byte HAN3);

#define SSD1306_ADDRESS 0x78
MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
Adafruit_SSD1306_I2c *oled;

MicroBit uBit1;
MicroBitThermometer thermometer; 

int XPOS = 0;
int YPOS = 0;

byte HANFontImage[32] = {0, };

int main() {
	/*
  uBit1.init();
  uBit1.display.disable();
  */
  
	if (oled != NULL) delete oled;
	oled = new Adafruit_SSD1306_I2c(i2c, SSD1306_ADDRESS, 64, 128);

	char str[20];
	char mymsg[] = "마이크로비트";
	char mymsg2[] = "온도 : %d";
	
	// 일반 문자열 출력
	oled->printf("%s", "bluexmas.tistory.com");
	
	// 한글 출력
	matrixPrint(XPOS,YPOS+20,mymsg);
	//matrixPrint(XPOS,YPOS+20+16,mymsg2);
	
  oled->display();
  
  while(true) {
  	oled->	fillRect(XPOS,YPOS+20+16, 100, 16, BLACK); // 지우기
  	
  	// 마이크로비트 내장 온도 가져오기
  	int curr_ther = thermometer.getTemperature();
  	sprintf(str, mymsg2, curr_ther);
  	
  	// 온도값 출력
  	matrixPrint(XPOS,YPOS+20+16,str);
  	oled->display();
  	
  	// 1초 대기
  	wait_us(1000); 
  }
}

void matrixPrint(int XPOS,int YPOS,char *pChar){
  byte rg = 3;   //<b1> red, <b0> green
  byte *pFs;
  byte i, b;
  byte c, c2, c3;

  while(*pChar){ 
    c = *(byte*)pChar++;

    //---------- 한글 ---------
    if(c >= 0x80){
      c2 = *(byte*)pChar++;
      c3 = *(byte*)pChar++;
      //Serial.print(c,DEC);
      //Serial.print(c2,DEC);
      //Serial.print(c3,DEC);      
      pFs = getHAN_font(c, c2, c3);
      oled->drawBitmap(XPOS, YPOS,  pFs, 16, 16, 1);
      XPOS = XPOS+16;
      if(XPOS > 128){
        XPOS = 0;
        YPOS = YPOS+16;
      }
    }
    //---------- ASCII ---------
    else{
      pFs = (byte*)ASCfontSet + ((byte)c - 0x20) * 16;
      oled->drawBitmap(XPOS, YPOS,  pFs, 8, 16, 1);
      XPOS = XPOS+8;
      if(XPOS > 128){
        XPOS = 0;
        YPOS = YPOS+16;
      }   
    }   
  }  
}  


/*=============================================================================
      한글 font 처리부분 
  =============================================================================*/

byte *getHAN_font(byte HAN1, byte HAN2, byte HAN3){

  const byte cho[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 3, 3, 1, 2, 4, 4, 4, 2, 1, 3, 0 };
  const byte cho2[] = { 0, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 6, 6, 7, 7, 7, 6, 6, 7, 5 };
  const byte jong[] = { 0, 0, 2, 0, 2, 1, 2, 1, 2, 3, 0, 2, 1, 3, 3, 1, 2, 1, 3, 3, 1, 1 };

  uint16_t utf16;
  byte first, mid, last;
  byte firstType, midType, lastType;
  byte i;
  byte *pB, *pF;

  /*------------------------------
    UTF-8 을 UTF-16으로 변환한다.

    UTF-8 1110xxxx 10xxxxxx 10xxxxxx
  */------------------------------
  utf16 = (HAN1 & 0x0f) << 12 | (HAN2 & 0x3f) << 6 | HAN3 & 0x3f;

  /*------------------------------
    초,중,종성 코드를 분리해 낸다.

    unicode = {[(초성 * 21) + 중성] * 28}+ 종성 + 0xAC00

          0   1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 
    초성 ㄱ   ㄲ ㄴ ㄷ ㄸ ㄹ ㅁ ㅂ ㅃ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ
    중성 ㅏ   ㅐ ㅑ ㅒ ㅓ ㅔ ㅕ ㅖ ㅗ ㅘ ㅙ ㅚ ㅛ ㅜ ㅝ ㅞ ㅟ ㅠ ㅡ ㅢ ㅣ  
    종성 없음 ㄱ ㄲ ㄳ ㄴ ㄵ ㄶ ㄷ ㄹ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅁ ㅂ ㅄ ㅅ ㅆ ㅇ ㅈ ㅊ ㅋ ㅌ ㅍ ㅎ
  ------------------------------*/
  utf16 -= 0xac00;
  last = utf16 % 28;
  utf16 /= 28;
  mid = utf16 % 21;
  first = utf16 / 21;

  first++;
  mid++;

  /*------------------------------
    초,중,종성 해당 폰트 타입(벌)을 결정한다.
  ------------------------------*/

  /*
   초성 19자:ㄱㄲㄴㄷㄸㄹㅁㅂㅃㅅㅆㅇㅈㅉㅊㅋㅌㅍㅎ
   중성 21자:ㅏㅐㅑㅒㅓㅔㅕㅖㅗㅘㅙㅚㅛㅜㅝㅞㅟㅠㅡㅢㅣ
   종성 27자:ㄱㄲㄳㄴㄵㄶㄷㄹㄺㄻㄼㄽㄾㄿㅀㅁㅂㅄㅆㅇㅈㅊㅋㅌㅍㅎ

   초성
      초성 1벌 : 받침없는 'ㅏㅐㅑㅒㅓㅔㅕㅖㅣ' 와 결합
      초성 2벌 : 받침없는 'ㅗㅛㅡ'
      초성 3벌 : 받침없는 'ㅜㅠ'
      초성 4벌 : 받침없는 'ㅘㅙㅚㅢ'
      초성 5벌 : 받침없는 'ㅝㅞㅟ'
      초성 6벌 : 받침있는 'ㅏㅐㅑㅒㅓㅔㅕㅖㅣ' 와 결합
      초성 7벌 : 받침있는 'ㅗㅛㅜㅠㅡ'
      초성 8벌 : 받침있는 'ㅘㅙㅚㅢㅝㅞㅟ'

   중성
      중성 1벌 : 받침없는 'ㄱㅋ' 와 결합
      중성 2벌 : 받침없는 'ㄱㅋ' 이외의 자음
      중성 3벌 : 받침있는 'ㄱㅋ' 와 결합
      중성 4벌 : 받침있는 'ㄱㅋ' 이외의 자음

   종성
      종성 1벌 : 중성 'ㅏㅑㅘ' 와 결합
      종성 2벌 : 중성 'ㅓㅕㅚㅝㅟㅢㅣ'
      종성 3벌 : 중성 'ㅐㅒㅔㅖㅙㅞ'
      종성 4벌 : 중성 'ㅗㅛㅜㅠㅡ'

  */
  if(!last){  //받침 없는 경우
    firstType = cho[mid];
    if(first == 1 || first == 24) midType = 0;
    else midType = 1;
  }
  else{       //받침 있는 경우
    firstType = cho2[mid];
    if(first == 1 || first == 24) midType = 2;
    else midType = 3;
    lastType = jong[mid];
  }
  memset(HANFontImage, 0, 32);

  //초성 
  pB = HANFontImage;
  pF = (byte*)KSFont + (firstType*20 + first)*32;
  i = 32;
  while(i--) *pB++ = pgm_read_byte(pF++); 

  //중성
  pB = HANFontImage;
  pF = (byte*)KSFont + (8*20 + midType*22 + mid)*32;
  i = 32;
  while(i--) *pB++ |= pgm_read_byte(pF++); 

  //종성
  if(last){
    pB = HANFontImage;
    pF = (byte*)KSFont + (8*20 + 4*22 + lastType*28 + last)*32;
    i = 32;
    while(i--) *pB++ |= pgm_read_byte(pF++); 
  }

  return HANFontImage;
}

static byte c1;  // Last character buffer

byte utf8ascii(byte ascii) {
    if ( ascii<128 )   // Standard ASCII-set 0..0x7F handling  
    {   c1=0;
        return( ascii );
    }

    // get previous input
    byte last = c1;   // get last char
    c1=ascii;         // remember actual character

    switch (last)     // conversion depnding on first UTF8-character
    {   case 0xC2: return  (ascii);  break;
        case 0xC3: return  (ascii | 0xC0);  break;
        case 0x82: if(ascii==0xAC) return(0x80);       // special case Euro-symbol
    }

    return  (0);                                     // otherwise: return zero, if character has to be ignored
}

void utf8ascii(char* s)
{      
        int k=0;
        char c;
        for (int i=0; i<strlen(s); i++)
        {
                c = utf8ascii(s[i]);
                if (c!=0)
                        s[k++]=c;
        }
        s[k]=0;
}
/*=============================================================================

  =============================================================================*/

실행 결과

댓글
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함