LoginSignup
3
1

More than 1 year has passed since last update.

【それM5StickCでも出来るもん】【第2話】ATOMDisplayっぽいのをESP_8_BIT_composite(ビデオ出力)にLovyanGFXを絡めて作る話

Posted at

1. はじめに

昨日の投稿で LovyanGFX の製作者さんやlang-shipさんからご助言を頂けました
ありがとうございます
おかげさまで 全画面の転送に成功いたしましたっ

2. 全ソース

ESPDisplay.v0.ino
/*

 +---------------------+                       +---------------------+
 | LovyanGFX Sprite    |                       |ESP_8_BIT_composite  |
 | 256 x 240 x RGB332  | spr.readRect          |256 x 240 x RGB332   |
 |                     | **getFrameBufferLines |                     |
 |                     |            =>         |                     | 
 |                     |                       | RCA(G26)            |
 |                     |                       | GND                 |
 +---------------------+                       +---------------------+

  #### caution ####
  edit ESP_8_BIT_composite.cpp:25   #define USE_DAC_CH (DAC_CHANNEL_2)
  edit ESP_8_BIT_composite.cpp:116  dac_output_enable (USE_DAC_CH);
  edit ESP_8_BIT_composite.cpp:687  dac_output_disable(USE_DAC_CH);

*/

#include "Lcd.h"
#include "Video.h"

uint32_t getFps()
{
  static uint32_t psec = 0;
  static uint32_t cnt = 0;
  static uint32_t fps = 0;
  uint32_t sec = 0;

  sec = millis() / 1000;
  ++cnt;
  if (psec != sec) {
    psec = sec;
    fps = cnt;
    cnt = 0;
  }
  return fps;
}

void setup()
{
  Serial.begin( 115200 );
  lcd.init();
  lcd.setRotation(1);
  lcd.setBrightness(128);
  lcd.fillScreen(TFT_BLACK);
  lcdWidth = lcd.width();
  lcdHeight = lcd.height();

  Serial.printf("lcd:%d,%d\n", lcdWidth, lcdHeight);
  Serial.printf("vdo:%d,%d\n", videoWidth, videoHeight);

  spr.setColorDepth(8);
  spr.createSprite(videoWidth, videoHeight);
  //  spr.setFont(&lgfxJapanMincho_16); // Japanese font ready !
  setupVideo();
}

void draw()
{
  uint16_t stp = 8;
  uint16_t hstp = stp/2;
  uint16_t cx = 0;
  uint16_t cy = 0;
  static uint16_t x = cx;
  static uint16_t y = cy;
  static uint16_t lx = stp;
  static uint16_t ly = stp;

  spr.fillScreen(TFT_BLACK);

  for (int x = 0; x < videoWidth;  x += stp) {
    spr.drawLine(x, 0, x, videoHeight - 1, TFT_BLUE);
  }
  for (int y = 0; y < videoHeight; y += stp) {
    spr.drawLine(0, y, videoWidth - 1, y, TFT_BLUE);
  }
  if ((x > videoWidth) || (x < 0)) lx = lx * -1;
  if ((y > videoHeight) || (y < 0)) ly = ly * -1;
  x = x + lx;
  y = y + ly;
  spr.drawLine(x+hstp, 0, x+hstp, videoHeight - 1, TFT_GREEN);
  spr.drawLine(0, y+hstp, videoWidth - 1, y+hstp, TFT_GREEN);
  spr.fillRect(x + 1, y + 1, stp - 2, stp - 2, TFT_RED);

  spr.setCursor(4, 8);
  spr.printf("%3dx%3d %3dfps [%3d,%3d]", videoWidth, videoHeight, getFps(), x, y);
  spr.setCursor(100, 220);
  spr.printf("Thx. Lovyan03/lang-ship");

}

void loop()
{
  draw();
  execCapture(); // Capture and send video
  delay(1);
}
Lcd.h
#define _M5DISPLAY_H_
class M5Display {};

//#include <M5StickC.h>
//#include <M5Stack.h>
//#include <M5Atom.h>

#include <LovyanGFX.hpp>
static LGFX lcd;
static LGFX_Sprite spr;

static uint16_t lcdWidth = 0;
static uint16_t lcdHeight = 0;
Video.h
#include "ESP_8_BIT_composite.h"
ESP_8_BIT_composite video(true /* = NTSC */);

static bool _videoEnable = false;
static const uint16_t videoHeight = 240;
static const uint16_t videoWidth  = 256;
static const uint16_t videoSize = (videoWidth * videoHeight);
static uint8_t _videoBuf[videoSize];

void setupVideo()
{
  video.begin();
}

void sendVideo()
{
  uint8_t **videoFb = video.getFrameBufferLines();
  uint16_t srcPos = 0;
  uint16_t ypos = 0;
  for (uint16_t i = 0; i < videoHeight; i++) {
    memcpy(&videoFb[ypos][0], &_videoBuf[srcPos], videoWidth);
    srcPos += videoWidth;
    ypos ++;
  }
  video.waitForFrame();
  videoFb = NULL;
}

void execCapture()
{
  uint16_t lines = 1; // lcd captire lines 1..20
  uint8_t pxls[videoWidth * lines];

  bool swap = lcd.getSwapBytes();
  uint16_t dstPos = 0;

  lcd.setSwapBytes(true);
  for (uint16_t y = 0; y < videoHeight; y += lines) {
    spr.readRect(0, y, videoWidth, lines, pxls);
    uint16_t srcPos = 0;
    for (uint16_t i = 0; i < lines; i++) {
      memcpy(&_videoBuf[dstPos], &pxls[srcPos], videoWidth);
      srcPos += videoWidth;
      dstPos += videoWidth;
    }
  }
  lcd.setSwapBytes(swap);
  sendVideo();
}

3.まとめ

いつも見守ってくださるlang-shipさんのブログ
素晴らしい高速な描画ルーチンLovyanさんのGFXには感謝です
今後ともよろしくお願い申し上げます

4.おまけ

さぁこれで準備は整った
本来の目的である ESPMiraCastっぽいのを作れます(謎
第3話をお楽しみに~

3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1