LovyanGFXで画面描画(13):文字がスクロールするサイネージを作る


LEDパネルキットを使って、簡単なサイネージを作り、コミケのブースで使いました。

64x32 のパネルをまずは LovyanGFX for PC を使って画面を構築。
![Screenshot from 2022-12-31 23-34-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/835fb416-fad1-cae7-aec7-8a0598d8f3c8.png)

真ん中の行がスクロールします。
安易にスプライト機能を使い、スプライトをずらして表示しているだけです。

以下のようなスケッチです。

```

#include <LovyanGFX.hpp>
#include <LGFX_AUTODETECT.hpp>
#include "arduinolib_for_PC.hpp"


LGFX display ( 64,32,3 );
static LGFX_Sprite sprite1(&display);
static LGFX_Sprite sprite2(&display);
static LGFX_Sprite sprite3(&display);

void setup() {
  display.init();
  display.setSwapBytes(true); 
  display.setTextSize(1);
  display.fillRect(0,0,64,8,display.color888(255,0,10));
  display.fillRect(0,24,64,32,display.color888(255,255,10));
  sprite1.createSprite(1000,16);
  sprite2.createSprite(1000,16);
  sprite3.createSprite(1000,16);
  display.setFont(&fonts::lgfxJapanGothicP_8 );
  sprite1.setFont(&fonts::lgfxJapanMinchoP_16 );
  sprite2.setFont(&fonts::lgfxJapanMinchoP_16 );
  sprite3.setFont(&fonts::lgfxJapanMinchoP_16 );
  sprite1.setTextColor(TFT_WHITE, TFT_BLACK);
  sprite2.setTextColor(TFT_BLUE, TFT_BLACK);
  sprite3.setTextColor(TFT_GREEN, TFT_BLACK);
  display.setCursor(0,0);
  display.setTextColor(TFT_BLACK, display.color888(255,0,10));
  display.println("秘密結社のブース");
  display.setCursor(0,24);
  display.setTextColor(TFT_BLACK, display.color888(255,255,10));
  display.println("オープンフォース");
  sprite1.println("秋葉原ロボット部の新刊 「ロボットの謎と不思議に挑戦する ロー」 ￥500");
  sprite2.println("秘密結社オープンフォース (委託) 宇宙軌道計算演習本 「宇宙への架け橋」 値下げ ￥50");
  sprite3.println("このキットは LEDパネルキットAKBONE2022 頒布中 パネルと基本キット ￥2000 ブースターパック￥2500");
}
```

これを、実際の 64X32のLEDパネルで使ったスケッチに直したものが以下のとおりです。

```

#define LGFX_USE_V1
#include <LovyanGFX.hpp>

struct LGFX_HUB75 : public lgfx::LGFX_Device
{
  // 座標を8ドット単位で逆順にする関数
  static void convertCoordinate(uint_fast16_t &x, uint_fast16_t &y)
  {
    if (!(x & 8)) { x = x ^ 7; }
  }


  lgfx::Bus_HUB75 _bus_instance;

// 1枚だけで使用する場合はこちら
  lgfx::Panel_HUB75 _panel_instance;

// 2枚以上接続する場合はこちら
// lgfx::Panel_HUB75_Multi _panel_instance;

  LGFX_HUB75(void)
  {

// X 座標が8ドット単位で逆順になるパネルの場合、座標変換関数を使用するよう指定する
  _panel_instance.convertCoordinate = convertCoordinate;

    {
      auto cfg = _bus_instance.config();

      // I2Sのポート番号を指定する。もし同時にI2S_DACを使用したい場合は 1に設定する。
      // (※ I2S_DACはポート0専用なので、HUB75ではポート1を使用することでDAC用にポート0を空けておく)
      cfg.port = 1;


   // 64x32パネル用
      cfg.pin_r1 = GPIO_NUM_33; // R1
      cfg.pin_r2 = GPIO_NUM_18; // R2
      cfg.pin_g1 = GPIO_NUM_32; // G1
      cfg.pin_g2 = GPIO_NUM_19; // G2
      cfg.pin_b1 = GPIO_NUM_25; // B1
      cfg.pin_b2 = GPIO_NUM_5 ; // B2
  /*/ // 128/64パネル用
      cfg.pin_r1 = GPIO_NUM_32; // R1
      cfg.pin_r2 = GPIO_NUM_19; // R2
      cfg.pin_g1 = GPIO_NUM_25; // G1
      cfg.pin_g2 = GPIO_NUM_5 ; // G2
      cfg.pin_b1 = GPIO_NUM_33; // B1
      cfg.pin_b2 = GPIO_NUM_18; // B2
  //*/
      cfg.pin_lat = GPIO_NUM_17; // LAT
      cfg.pin_oe  = GPIO_NUM_16; // OE
      cfg.pin_clk = GPIO_NUM_4 ; // CLK

      cfg.pin_addr_a = GPIO_NUM_12;
      cfg.pin_addr_b = GPIO_NUM_14;
      cfg.pin_addr_c = GPIO_NUM_27;
      cfg.pin_addr_d = GPIO_NUM_26;
      cfg.pin_addr_e = GPIO_NUM_2;

      // データ送信速度
      cfg.freq_write = 13333334;

      // パネルの行選択の仕様に応じて指定する
      //cfg.address_mode = cfg.address_shiftreg;
       cfg.address_mode = cfg.address_binary;

      // LEDドライバチップの種類を指定する
      cfg.led_driver = cfg.led_driver_standard;
 //      cfg.led_driver = cfg.led_driver_FM6124;

      // DMA用のタスクの優先度 (FreeRTOSのタスク機能を使用)
      cfg.task_priority = 2;

      // DMA用のタスクに使用するCPUコア設定 (FreeRTOSのタスク機能を使用)
      cfg.task_pinned_core = PRO_CPU_NUM;
      // cfg.task_pinned_core = APP_CPU_NUM;

      _bus_instance.config(cfg);
      _panel_instance.setBus(&_bus_instance);
    }

    {
      auto cfg = _panel_instance.config();

      // ここでパネルサイズを指定する
      // 複数枚使用する場合(Panel_HUB75_Multi使用時) は表示領域全体の縦横サイズを指定
      cfg.memory_width  = cfg.panel_width  = 64;
      cfg.memory_height = cfg.panel_height = 32;

      _panel_instance.config(cfg);
      setPanel(&_panel_instance);
    }

/*
// 複数枚使用する場合(Panel_HUB75_Multi使用時) この設定を行う
    {
      auto cfg = _panel_instance.config_detail();

      // 構成パネルの総枚数を指定
      cfg.panel_count = 3;

      // パネル1枚の幅を指定
      cfg.single_width = 128;

      // パネル1枚の高さを指定
      cfg.single_height = 64;

      _panel_instance.config_detail(cfg);

      // 各パネルの配置座標を設定する
      //  _panel_instance.setPanelPosition( パネル通し番号, 横座標, 縦座標, 回転方向);
      _panel_instance.setPanelPosition( 0,   0,   0,   0);
      _panel_instance.setPanelPosition( 1, 128,   0,   1);
      _panel_instance.setPanelPosition( 2,   0,  64,   2);
    }
//*/
  }
};

LGFX_HUB75 display;
static LGFX_Sprite sprite1(&display);
static LGFX_Sprite sprite2(&display);
static LGFX_Sprite sprite3(&display);


void setup() {


  // 色深度は 8bit(RGB332)と 16bit(RGB565) が設定可能
  display.setColorDepth(8);
  display.init();
  display.setSwapBytes(true); 
  display.setTextSize(1);
  display.fillRect(0,0,64,8,display.color888(255,0,10));
  display.fillRect(0,24,64,32,display.color888(255,255,10));
  sprite1.createSprite(1000,16);
  sprite2.createSprite(1000,16);
  sprite3.createSprite(1000,16);
  display.setFont(&fonts::lgfxJapanGothicP_8 );
  sprite1.setFont(&fonts::lgfxJapanMinchoP_16 );
  sprite2.setFont(&fonts::lgfxJapanMinchoP_16 );
  sprite3.setFont(&fonts::lgfxJapanMinchoP_16 );
  sprite1.setTextColor(TFT_WHITE, TFT_BLACK);
  sprite2.setTextColor(TFT_BLUE, TFT_BLACK);
  sprite3.setTextColor(TFT_GREEN, TFT_BLACK);
  display.setCursor(0,0);
  display.setTextColor(TFT_BLACK, display.color888(255,0,10));
  display.println("秘密結社のブース");
  display.setCursor(0,24);
  display.setTextColor(TFT_BLACK, display.color888(255,255,10));
  display.println("オープンフォース");
  sprite1.println("秋葉原ロボット部の新刊 「ロボットの謎と不思議に挑戦する ロー」 ￥500");
  sprite2.println("秘密結社オープンフォース (委託) 宇宙軌道計算演習本 「宇宙への架け橋」 値下げ ￥50");
  sprite3.println("このキットは LEDパネルキットAKBONE2022 頒布中 パネルと基本キット ￥2000 ブースターパック￥2500");
}
```