M5StickCのキャプチャ実験

f:id:nicotakuya:20210226153653j:plain
M5StickCのキャプチャ

M5StickCのキャプチャできないか試してみました。まだ実験中です。
こちらの記事を参考にさせて頂きました。
raspberrypi.mongonta.com
これによると、ライブラリの「In_eSPI_Setup.h」というファイルを修正すると、「readPixel」が使えるようになるとのこと。readPixelは指定座標の画面のカラーコードを読み取るための関数です。
具体的な手順は以下のとおり。
「C:\Users\(ユーザー名)\Documents\Arduino\libraries\M5StickC\src\utility」フォルダの中にある「In_eSPI_Setup.h」をテキストエディタで開いて、次の2点を修正します。

f:id:nicotakuya:20210226151729p:plain
修正1

(修正1)「TFT_SDA_READ」の左側にある「//」を削除する。

f:id:nicotakuya:20210226151808p:plain
修正2

(修正2)「SPI_READ_FREQUENCY」の値を変更する。適切な値がわかりませんが「4000000」にしました。ビットレートが大きいと通信に失敗するようです。

↓が実験用のプログラムです。M5StickCに書き込むArduinoのスケッチです。Aボタン(M5ボタン)が押されたら、画面のデータをシリアルポートから出力します。

// capture
#include <M5StickC.h>

void capture(void){
  unsigned int color;
  int x,y;

  if(digitalRead(M5_BUTTON_HOME) == HIGH)return;
  while(digitalRead(M5_BUTTON_HOME) == LOW);

  for(y=0; y<80; y++){
    for(x=0; x<160; x++){
        color = M5.Lcd.readPixel(x,y);
        Serial.write((unsigned char)(color & 0xff));
        Serial.write((unsigned char)(color >> 8));
        Serial.flush();  // シリアル出力完了を待つ
    }  
  }  
}

void setup() {
  M5.begin();
  M5.Lcd.setRotation(3);
  M5.Lcd.setTextSize(3);
  M5.Lcd.setTextColor(RED);
  M5.Lcd.print("HELLO WORLD");
  M5.Lcd.setTextColor(BLUE);
  M5.Lcd.print("HELLO WORLD");
  M5.Lcd.setTextColor(GREEN);
  M5.Lcd.print("HELLO WORLD");
}

void loop() {
  capture();
}

そして、
↓がパソコン側の受信用のプログラムです。HSP3(Windows)で動きます。シリアルポートから受信した内容を画面に描画します。

//---------------------------------------------------------
//  for HSP 3   by takuya matsubara
// ・M5StickCのキャプチャを受信
//---------------------------------------------------------
#include "hspext.as"

#define LEDWIDTH  160	//width pixel
#define LEDHEIGHT 80	//height pixel
#define OFFSETX 0
#define OFFSETY 0
#define DOTSZ 3
#define BAUDRATE 115200

sdim livebuf,LEDWIDTH*LEDHEIGHT
screen 0,800,512,0,0,0
dispw = DOTSZ*LEDWIDTH
disph = DOTSZ*LEDHEIGHT
flag_comm =0
objsize 70,25
pos 0,400
button gosub "Open",*connect
pos 70*3+10,400
print "COMM"
pos 70*3+50,400
comnum=0
combox comnum,150,"com\ncom1\ncom2\ncom3\ncom4\ncom5\ncom6\ncom7\ncom8\ncom9\ncom10\n"
pos 70*6,400
button gosub "Save BMP",*savegrp

x1=OFFSETX
y1=OFFSETY
ptr=0
colordata=0
repeat
	if(flag_comm==0){
		wait 1
	}else{
		//recv
		repeat
			comgetc btn	//recv 1byte
			if(stat != 0){
				if(ptr==0):colordata = btn
				if(ptr==1):colordata = (btn<<8)+colordata
				ptr = (ptr+1) \ 2
				if(ptr==0){
					red  = (colordata >> (5+6)) & $1f	//32諧調
					green= (colordata >> 5) & $3f	//64諧調
					blue = colordata & $1f	//32諧調
					x2 = x1+DOTSZ-1
					y2 = y1+DOTSZ-1
					red = red*255/$1f
					green = green*255/$3f
					blue = blue*255/$1f

					//暗いので2倍にする(原因不明)
					red*=2
					green*=2
					blue*=2
					if red>255:red=255
					if green>255:green=255
					if blue>255:blue=255
					color red,green,blue
					boxf x1,y1,x2,y2
					
					x1 += DOTSZ
					if(x1 >= ((DOTSZ*LEDWIDTH)+OFFSETX)){
						x1=OFFSETX
						y1+=DOTSZ
						if(y1 >= ((DOTSZ*LEDHEIGHT)+OFFSETY)){
							y1 = OFFSETY
						}
					}
				}
			}else{
				redraw 1
				wait 1	//no data
				redraw 0
			}
		loop
	}
loop	
end

//-------------
*savegrp
gosub *connect_close
dialog "bmp",17,"BMPファイル"
if stat==0:return
filename=refstr
screen 1,LEDWIDTH*DOTSZ,LEDHEIGHT*DOTSZ
gsel 1,1
pos 0,0
gcopy 0,0,0,LEDWIDTH*DOTSZ,LEDHEIGHT*DOTSZ
bmpsave filename
gsel 1,-1
gsel 0,0
return
	
*connect_open
	if(flag_comm = 0){
		comopen comnum,"baud="+str(BAUDRATE)+" parity=N data=8 stop=1"
		if stat : dialog "COM"+comnum+"は使えません" : end
		flag_comm=1

		repeat
			comgetc btn	//recv 1byte
			if(stat == 0):break
		loop
		ptr=0
		x1=OFFSETX
		y1=OFFSETY
	}
	return

*connect_close
	if(flag_comm = 1){
		comclose
		flag_comm=0
	}
	return

*connect
	if(flag_comm =0){
		gosub *connect_open
		title "OPEN COMM"+str(comnum)
		wait 150	//必須
	}else{
		gosub *connect_close
		title "CLOSE COMM"
	}
	return

M5StickCをパソコンのUSBポートに接続してある状態で上記のプログラムを実行します。

f:id:nicotakuya:20210226151149p:plain
実行結果

画面の「OPEN」ボタンを押してシリアルポートの回線を開きます。M5StickCのAボタン(M5ボタン)を押すと、画像データが転送されます。通信速度は115200bpsです。
未解決の問題ですが、受信したカラーコードはすべて、想定の半分になってしまいます。ここままだと画像が暗くなってしまうので、受信した直後に2倍にして描画しています。各色ずつ1bit足りないので、16bitカラーではなく、13bitカラーになっていると思います。