M5Stackで日本語表示






導入方法が比較的シンプルで、高い解像度の文字にも対応した下記ライブラリを利用することで、M5Stackのディスプレイに綺麗な日本語文字を表示させることができました。

[Arduino用漢字フォントライブラリ SDカード版](https://github.com/Tamakichi/Arduino-KanjiFont-Library-SD)


### **実行環境**
* Windows7 pro 64bit
* Arduino IDE 1.8.6
* M5stack(Library) 0.2.2


## **利用方法**

インストール及び利用方法は、READMEに記載されているように
>
* /liblary/sdfonts フォルダをArduinoのliblaryにコピーする。
* /fontbin フォルダ内の FONT.BIN、FONTLCD.BIN をSDカードの直下に入れる。

だけです。ただし、M5Stackでの使用に際し、私の環境（`Arduino IDE 1.8.6`）では下記の様な修正が必要でした。（使用環境によって異なる可能性がありますのでご参考まで）


### **修正内容**

`libraries/sdfonts.h`　26行目

```c++
// #define MYSDCLASS SDClass
#define MYSDCLASS SDFS
```



`libraries/sdfonts.cpp`　24行目

```c++
// #define FONTFILE   "FONT.BIN"     // フォントファイル名
// #define FONT_LFILE "FONTLCD.BIN"  // グラフィック液晶用フォントファイル名
#define FONTFILE   "/FONT.BIN"
#define FONT_LFILE "/FONTLCD.BIN"
```


## **実行したプログラム**

作成したM5Stack用のスケッチはこちらです。
`libraries/sdfonts/exsample/sample1/sample1.ino`を殆どそのまま利用させて貰いました。


```c++
#include <M5Stack.h>
#include <sdfonts.h>

#define SD_PN 4

// フォントデータの表示
// buf(in) : フォント格納アドレス
// ビットパターン表示
// d: 8ビットパターンデータ
void fontDisp(uint16_t x, uint16_t y, uint8_t* buf) {
  uint32_t txt_color = TFT_WHITE;
  uint32_t bg_color = TFT_BLACK;

  uint8_t bn = SDfonts.getRowLength();               // 1行当たりのバイト数取得
  Serial.print(SDfonts.getWidth(), DEC);            // フォントの幅の取得
  Serial.print("x");
  Serial.print(SDfonts.getHeight(), DEC);           // フォントの高さの取得
  Serial.print(" ");
  Serial.println((uint16_t)SDfonts.getCode(), HEX); // 直前し処理したフォントのUTF16コード表示

  for (uint8_t i = 0; i < SDfonts.getLength(); i += bn ) {
    for (uint8_t j = 0; j < bn; j++) {
      for (uint8_t k = 0; k < 8; k++) {
        if (buf[i + j] & 0x80 >> k) {
          M5.Lcd.drawPixel(x + 8 * j + k , y + i / bn, txt_color);
        } else {
          M5.Lcd.drawPixel(x + 8 * j + k , y + i / bn, bg_color);
        }
      }
    }
  }
}


// 指定した文字列を指定したサイズで表示する
// pUTF8(in) UTF8文字列
// sz(in)    フォントサイズ(8,10,12,14,16,20,24)
void fontDump(uint16_t x, uint16_t y, char* pUTF8, uint8_t sz) {
  uint8_t buf[MAXFONTLEN]; // フォントデータ格納アドレス(最大24x24/8 = 72バイト)
  SDfonts.open();                                   // フォントのオープン
  SDfonts.setFontSize(sz);                          // フォントサイズの設定
  uint16_t mojisu = 0;
  while ( pUTF8 = SDfonts.getFontData(buf, pUTF8) ) { // フォントの取得
    fontDisp(x + mojisu * sz, y, buf);                 // フォントパターンの表示
    ++mojisu;
  }

  SDfonts.close();                                  // フォントのクローズ
}


void setup() {
  Serial.begin(115200);

  M5.begin();

  M5.Lcd.setBrightness(100);
  M5.Lcd.fillScreen(TFT_BLACK);

  SDfonts.init(SD_PN);
  Serial.println(F("sdfonts liblary"));

  fontDump(50, 10, "日本語の表示", 16);
  fontDump(50, 40, "日本語の表示", 20);
  fontDump(50, 80, "日本語の表示", 24);

}

void loop() {
  // put your main code here, to run repeatedly:
}

```

## **結果**

![DSCN2333.jpg](https://qiita-image-store.s3.amazonaws.com/0/264410/38fb2678-97c8-e24c-77c3-7518b493e882.jpeg)

ピンボケですみません・・・

## **＜追記＞文字をスクロール**

`TFT_eSprite`で文字をスクロールさせてみました。

```c++

#include <M5Stack.h>
#include <sdfonts.h>

#define SD_PN 4

#define TFT_WIDTH  320
#define TFT_HEIGHT 240

#define FONT_SIZE 24 // スクロール文字のサイズ（ドット）
#define OFFSET 3

#define SPRITE_WIDTH TFT_WIDTH * 5 // Spriteの幅を大きめにとっておく
#define SPRITE_HEIGHT FONT_SIZE + OFFSET * 2 // フォントの高さより少し大きくした

#define SCROLL_WIDTH SPRITE_WIDTH
//#define SCROLL_HEIGHT SPRITE_HEIGHT
#define SCROLL_HEIGHT 15 // わざと SPRITE_HEIGHT の半分にして、文字の上半分だけスクロール

#define STRIDE_X -1 // スクロールの向きとストライド（横軸）
#define STRIDE_Y 0 // スクロールの向きとストライド（縦軸）
#define WAIT_TIME 0 // スクロールスピード調整用

TFT_eSprite text_sp = TFT_eSprite(&M5.Lcd);

int16_t counts_to_go = 0;
uint16_t word_counts = 0; // 表示した文字の数

char* scrol_char = "スクロールテスト用の長い文字列です";

void fontDisp(uint16_t x, uint16_t y, uint8_t* buf, TFT_eSPI* esp) {
  uint32_t txt_color = TFT_WHITE;
  uint8_t bn = SDfonts.getRowLength();               // 1行当たりのバイト数取得
  for (uint8_t i = 0; i < SDfonts.getLength(); i += bn ) {
    for (uint8_t j = 0; j < bn; j++) {
      for (uint8_t k = 0; k < 8; k++) {
        if (buf[i + j] & 0x80 >> k) {
          esp->drawPixel(x + 8 * j + k , y + i / bn, txt_color);
        }
      }
    }
  }
}

uint16_t fontDump(uint16_t x, uint16_t y, char* pUTF8, uint8_t sz, TFT_eSPI* esp = &M5.Lcd) {
  uint8_t buf[MAXFONTLEN]; // フォントデータ格納アドレス(最大24x24/8 = 72バイト)
  SDfonts.open();                                   // フォントのオープン
  SDfonts.setFontSize(sz);                          // フォントサイズの設定
  uint16_t mojisu = 0;
  while ( pUTF8 = SDfonts.getFontData(buf, pUTF8) ) { // フォントの取得
    fontDisp(x + mojisu * sz, y, buf, esp);                 // フォントパターンの表示
    ++mojisu;
  }

  SDfonts.close(); // フォントのクローズ
  return mojisu; // 文字数を返す
}

void setup() {
  M5.begin();
  M5.Lcd.fillScreen(TFT_BLACK);

  SDfonts.init(SD_PN);

  // 固定文字の表示
  fontDump(0, 50, "↓この文字の上半分がスクロールします", 16);

  //Spriteの設定（スクロール文字用）
  text_sp.setColorDepth(8);//Spriteのcolour depth
  text_sp.createSprite(SPRITE_WIDTH, SPRITE_HEIGHT);//Spriteの幅と高さ
  text_sp.fillSprite(TFT_BLUE);
  text_sp.setScrollRect(0, 0, SCROLL_WIDTH, SCROLL_HEIGHT, TFT_BLUE); //Sprite内のスクロールする範囲と色
  word_counts = fontDump(0, OFFSET, scrol_char, FONT_SIZE, &text_sp);

}

void loop() {

  //位置を指定してSpriteを表示
  text_sp.pushSprite(0, 80);

  //スクロール方向・ストライドを指定
  text_sp.scroll(STRIDE_X, STRIDE_Y);

  counts_to_go --;
  if (counts_to_go <= 0)
  {
    counts_to_go = TFT_WIDTH + FONT_SIZE * word_counts;
    word_counts = fontDump(TFT_WIDTH, OFFSET, scrol_char, FONT_SIZE, &text_sp);
  }

  delay(WAIT_TIME);

}

```

静止画でも分かるように文字の上半分だけにしてみたけど、逆に分かり辛いかも・・・
![DSCN2339.jpg](https://qiita-image-store.s3.amazonaws.com/0/264410/90e11344-81dc-4308-90a1-8e7dcf381edf.jpeg)





## **参考にさせて頂きました**
* [arduino用漢字フォントライブラリSDカード版の製作（２）](http://nuneno.cocolog-nifty.com/blog/2016/05/arduinosd-b7ec.html)
* [M5Stackで日本語表示させてみる](https://qiita.com/inachi/items/0e492a6b00d31111e54d)