07.M5PaperS3でメニューtest


07.M5PaperS3でメニューtest

説明

次のブログで使用するための、メニュー画面を表示するだけのスケッチです。タッチで4変数を選択でき、SDのファイルも選択できるはずです。
ただし、ファイルは、SDの
・ルートにあるファイル
・8.3形式のファイル
・9ファイル以下
の制約があります。

スケッチ


// メニュー画面 960x540
// 各種設定とルートファイル(8.3)を選択
#include <SD.h>                      // SDを使用
File root;                           // Fileのインスタンスを作成
#include <epdiy.h>                   // 電子ペーパードライバー
#include <M5GFX.h>                   // M5Stack用グラフィックライブラリ
M5GFX display;                       // M5GFXのインスタンスを作成
#define SD_SPI_CS_PIN GPIO_NUM_47    // SDのpin
#define SD_SPI_SCK_PIN GPIO_NUM_39   // SDのpin
#define SD_SPI_MOSI_PIN GPIO_NUM_38  // SDのpin
#define SD_SPI_MISO_PIN GPIO_NUM_40  // SDのpin
bool edpQ = false;                   // (true)高品質or(false)高速
bool gamenTate = true;               // 画面(true)縦or(false)横
int16_t fontS = 32;                  // fontサイズ (32or36px)
int16_t gyoukan = 10;                // 行間px
int16_t menuDY = 70;                 // メニュー画面刻みpx
String fList[20][2];                 // [n][fName,fByte]
lgfx::touch_point_t tp[1];           // タッチポイント

void SetFont() {                                  // Font等初期化関数
  display.init();                                 // パネルの初期化
  if (display.isEPD()) {                          // e-Paper displayなら
    display.setEpdMode(epd_mode_t::epd_fastest);  // 描画速いが、低品質に設定
  }
  display.setRotation(0);  // 縦長に回転
  //display.setRotation(1);                     // 横長に回転
  display.fillScreen(TFT_WHITE);                // 全画面白
  display.setFont(&fonts::lgfxJapanGothic_32);  // 固定幅ゴシック体 8,12,16,20,24,28,32,36,40
  display.setTextColor(TFT_BLACK, TFT_WHITE);   // (字,地)
  display.setTextSize(1);                       // 文字サイズの倍数 1-7
  display.setTextWrap(true, true);              // 自動折返し(x,y)
  display.setCursor(0, 0);                      // カーソル位置
  display.setAutoDisplay(0);                    // 書込後即描画しない
}

void setup() {
  SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN,
            SD_SPI_MOSI_PIN, SD_SPI_CS_PIN);
  delay(100);  // 0.1秒待つ
  SetFont();   // Font等初期化関数へ

  Serial.begin(115200);                         // シリアル通信を開始し、ポートが開くのを待つ:
  if (!SD.begin(47)) {                          // SDライブラリとカードを初期化できなければ
    Serial.println("失敗 SDライブラリ初期化");  // 表示
    while (true)                                // 無限ループ
      ;
  }

  // -------------------------------- ファイル名取得
  root = SD.open("/");  // ルートのファイルを開く
  char buf[40];         // 作業用
  int8_t i = 0;
  while (true) {                                        // breakになるまで無限ループ
    File entry = root.openNextFile();                   // ディレクトリ内の次のファイルまたはホルダを取得
    if (!entry) break;                                  // 次のファイルまたはフォルダがないなら抜ける
    if (!entry.isDirectory()) {                         // ホルダでなければ
      fList[i][0] = String(entry.name());               // ファイル名を取得
      if (entry.size() < 1000) {                        // ファイルサイズが1kB未満なら
        sprintf(buf, " %5dB\n", entry.size());          // bufにファイルサイズ(bytes)を
      } else {                                          // 1kB以上なら
        sprintf(buf, " %4dkB\n", entry.size() / 1000);  // Bufにファイルサイズ(kB)を
      }
      fList[i][1] = String(buf);  // ファイルサイズ(B or kB単位)
      i++;                        // 次のファイル番号
    }
    entry.close();  // ファイルを閉じる
  }
}

void loop() {
  // -------------------------------- メニュー1行目セット
  int16_t menuX = 0, menuY = 20;                 // カーソル変数
  display.setCursor(menuX, menuY);               // カーソル位置
  if (edpQ == 1) {                               // 高品質画面なら
    display.print(" 品質・速度 : ");              // 表示をセット
    display.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    display.print("高品質");                     // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);  // (字,地)
    display.print("  高速");                   // 表示をセット
  } else {                                       // 高速画面なら
    display.print(" 品質・速度 : 高品質  ");    // 表示をセット
    display.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    display.print("高速");                       // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);  // (字,地)
  }

  // -------------------------------- メニュー2行目セット
  menuY += menuDY;                               // 次の行へ
  display.setCursor(menuX, menuY);               // カーソル位置
  if (gamenTate == 1) {                          // 縦画面なら
    display.print(" 画面向き  : ");              // 表示をセット
    display.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    display.print("縦向き");                     // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);  // (字,地)
    display.print("  横向き");                 // 表示をセット
  } else {                                       // 横画面なら
    display.print(" 画面向き  : 縦向き  ");    // 表示をセット
    display.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    display.print("横向き");                     // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);  // (字,地)
  }

  // -------------------------------- メニュー3行目セット
  menuY += menuDY;                               // 次の行へ
  display.setCursor(menuX, menuY);               // カーソル位置
  if (fontS == 32) {                             // fontサイズが32pxなら
    display.print(" Font Size : ");              // 表示をセット
    display.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    display.print("32px");                     // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);  // (字,地)
    display.print("  36px");                 // 表示をセット
  } else {                                       // fontサイズが36pxなら
    display.print(" Font Size : 32px  ");    // 表示をセット
    display.setTextColor(TFT_WHITE, TFT_BLACK);  // (字,地)
    display.print("36px");                     // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);  // (字,地)
  }

  // -------------------------------- メニュー4行目セット
  menuY += menuDY;                                  // 次の行へ
  display.setCursor(menuX, menuY);                  // カーソル位置
  if (gyoukan == 5) {                               // 行間が5pxなら
    display.print(" 行間(px) : ");                  // 行間px
    display.setTextColor(TFT_WHITE, TFT_BLACK);     // (字,地)
    display.print("05");                          // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);     // (字,地)
    display.print("  10  15");              // 表示をセット
  } else if (gyoukan == 10) {                       // 行間が10pxなら
    display.print(" 行間(px) : 05  ");          // 表示をセット
    display.setTextColor(TFT_WHITE, TFT_BLACK);     // (字,地)
    display.print("10");                          // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);     // (字,地)
    display.print("  15");                      // 表示をセット
  } else {                                          // 行間が15pxなら
    display.print(" 行間(px) : 05  10  ");  // 表示をセット
    display.setTextColor(TFT_WHITE, TFT_BLACK);     // (字,地)
    display.print("15");                          // 表示をセット
    display.setTextColor(TFT_BLACK, TFT_WHITE);     // (字,地)
  }

  // -------------------------------- ファイル名セット
  menuY += menuDY;                    // 次の行へ
  String fName;                       // ファイル名
  for (int8_t i = 0; i < 9; i++) {    // 9ファイルまで表示
    display.setCursor(menuX, menuY);  // カーソル位置
    display.printf("%3d ", i + 1);    // ファイル番号セット
    fName = fList[i][0]               // ファイル名
            + "         ";            // 9文字空白追加
    fName = fName.substring(0, 12);   // 頭から12文字
    display.print(fName);             // ファイル名セット
    display.print(fList[i][1]);       // ファイルサイズセット
    menuY += menuDY;                  // 次の行へ
  }

  // -------------------------------- 罫線セット 960x540
  for (int8_t i = 1; i < 5; i++) {  // 水平線上4本
    display.drawFastHLine(0, menuDY * i, 540, TFT_BLACK);
  }
  for (int8_t i = 5; i < 13; i++) {  // 水平線下8本
    display.drawFastHLine(0, menuDY * i, 400, TFT_BLACK);
  }
  display.drawFastVLine(335, 0, 210, TFT_BLACK);    // 垂直線上3行
  display.drawFastVLine(285, 210, 70, TFT_BLACK);   // 4行目左
  display.drawFastVLine(420, 210, 70, TFT_BLACK);   // 4行目右
  display.drawFastVLine(400, 280, 680, TFT_BLACK);  // 垂直線下ファイル行

  // -------------------------------- 文字セット
  display.setCursor(450, 500);  // カーソル位置
  display.print("戻");          // 表示をセット
  display.setCursor(450, 600);  // カーソル位置
  display.print("る");          // 表示をセット
  display.display();            // セットを表示

  // -------------------------------- タッチ判定
  bool drawed = false;               // 描画変数=描画していない
  if (display.getTouchRaw(tp, 1)) {  // タッチ情報を取得
    drawed = true;                   // 描画した
    if (tp[0].y < 70) {              // 1行目なら
      if (tp[0].x < 335) {           // 左側なら
        edpQ = 1;                    // 高品質
      } else {                       // 右側なら
        edpQ = 0;                    // 高速
      }
    } else if (tp[0].y < 140) {  // 2行目なら
      if (tp[0].x < 335) {       // 左側なら
        gamenTate = 1;           // 縦向き
      } else {                   // 右側なら
        gamenTate = 0;           // 横向き
      }
    } else if (tp[0].y < 210) {  // 3行目なら
      if (tp[0].x < 335) {       // 左側なら
        fontS = 32;              // 32px
      } else {                   // 右側なら
        fontS = 36;              // 36px
      }
    } else if (tp[0].y < 280) {    // 4行目なら
      if (tp[0].x < 285) {         // 左側なら
        gyoukan = 5;               // 行間5px
      } else if (tp[0].x < 420) {  // 中央なら
        gyoukan = 10;              // 行間10px
      } else {                     // 右側なら
        gyoukan = 15;              // 行間15px
      }
    } else if (tp[0].x > 400) {  // 5行目以下の右なら
      // 戻る
    } else if (tp[0].y < 350) {  // 5行目のfile1なら
      fName = fList[1][0];       // file1
    } else if (tp[0].y < 420) {  // 6行目のfile2なら
      fName = fList[2][0];       // file2
    } else if (tp[0].y < 490) {  // 7行目のfile3なら
      fName = fList[3][0];       // file3
    } else if (tp[0].y < 560) {  // 8行目のfile4なら
      fName = fList[4][0];       // file4
    } else if (tp[0].y < 630) {  // 9行目のfile5なら
      fName = fList[5][0];       // file5
    } else if (tp[0].y < 700) {  // 10行目のfile6なら
      fName = fList[6][0];       // file6
    } else if (tp[0].y < 770) {  // 11行目のfile7なら
      fName = fList[7][0];       // file7
    } else if (tp[0].y < 840) {  // 12行目のfile8なら
      fName = fList[8][0];       // file8
    } else {                     // 13行目のfile9なら
      fName = fList[9][0];       // file9
    }
  } else if (drawed) {  // もし描画していれば
    drawed = false;     // 描画変数を戻す
  }
  vTaskDelay(1);  // 1tickの間タスクをブロック
}
* flash memory(1.3Mbyte)のうち、スケッチが71%使用。RAM(327kbyte)のうち、global変数が6%使用、local変数で306kbyte使用可能。(1000byte=1kbyteで計算)