SSブログ

ATtiny412でNTSCビデオ信号 [Arduino]

NTSCでのビデオ出力。
いろいろ調べてみたけど、結構たいへん。

1.情報収集
小さなカラーLCDなども安価になってきていて、いまどきマイコンでNTSCでのビデオ出力する人が少なくなっている。記事をさぐると10年くらい前のものが多く、リンク切れも多数。
カラー、ノンインターレスの説明は見つかるものの、基本のモノクロとノンインターレスの情報が少なめ。PICでの情報が多めな感じ。

2.ソフトウェア
全部あるいは部分的にアセンブラを使わないといけなかったり、SPIを出力につかったり。
とくにカラーは超高難度のよう。
別ICと組み合わせが必要なものも。

3.ハードウェア
簡単なものだと同期信号と画像信号と2本の抵抗を介して出力。
外部クロックを使用しないと画像が揺らぐらしい。


そこで、C言語だけで、tinyAVR 1シリーズのDAC機能を使って、コネクタ以外の外付けパーツなしでビデオ出力できるかやってみました。
ntsc_tiny412.jpg

とりあえずできたけど、ウェイトなしで横16ドットしか表示できていない。
もうちょっとなんとかなりそうな気もする。
cap_ntsc_i_412.jpg

// ATtiny412 NTSC test (20MHz)
#define   IRE_p100  (59)        // = 255 * 1.0V/4.34V * (40+100)/140
#define   IRE_p50   (38)        // = 255 * 1.0V/4.34V * (40+ 50)/140
#define   IRE_0     (17)        // = 255 * 1.0V/4.34V *  40     /140
#define   IRE_m40   (0)

uint8_t const img_i[] = {
  0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,
  0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,
  0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
  0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,
  0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
  0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,
  0,0,0,0,1,1,1,0,0,1,1,0,0,0,0,0,
  0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,
  0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
  0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
  0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};

void setup(){                           // Register Settings
  // VIDEO OUTPUT
    VREF.CTRLA |= VREF_DAC0REFSEL_4V34_gc;              // Voltage reference at 4.34V
    VREF.CTRLB |= VREF_DAC0REFEN_bm;                    // DAC0/AC0 reference enable: enabled
    delayMicroseconds(25);                              // Wait VREF start-up time
    PORTA.PIN6CTRL &= ~PORT_ISC_gm;                     // Disable digital input buffer
    PORTA.PIN6CTRL |=  PORT_ISC_INPUT_DISABLE_gc;
    PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm;                // Disable pull-up resistor
    DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm;          // Enable DAC, Output Buffer
  // H-SYNC
    TCB0.CTRLA  = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm;// 20MHz / 1 / 1270 -> 15,750Hz
    TCB0.CTRLB  = TCB_CNTMODE_INT_gc;                   // periodic Interrupt mode
    TCB0_CCMP   = 1269;                                 // top value
    TCB0.INTCTRL= TCB_CAPT_bm;                          // Capture Interrupt Enable
}

void loop() {
}

ISR(TCB0_INT_vect) {
  static uint16_t scan, x, y, offset;
  DAC0.DATA = IRE_0;                                    // start from -3.2usec
  scan++;
  while(TCB0_CNT <  94);                                // front porch (20MHz*(3.2+1.5    )usec=94)
  DAC0.DATA = IRE_m40;
  if(scan > 3  && scan < 7)   goto END;
  while(TCB0_CNT < 188);                                // back porch  (20MHz*(3.2+1.5+4.7)usec=188)
  DAC0.DATA = IRE_0; 
  if(scan < 48 || scan > 239) goto END;                 // 192 lines
  y = (scan - 48) / 12;                                 // y = 0..15
  offset= y<<4;
  while(TCB0_CNT < 282);                                // H-blanking  (20MHz*(3.2+10.9   )usec=282)
  MAIN:
  for(x=0; x<16; x++) {
    DAC0.DATA = (img_i[x + offset]) ? IRE_p100 : IRE_0;
  }
  DAC0.DATA = IRE_0; 
  END:
  if(scan == 262) scan = 0;
  TCB0.INTFLAGS= TCB_CAPT_bm;                           // Clear Capture Interrupt Flag
}


[2023/11/02]
その後、ちょっと改善
・割り算をなくした
・16ビットでなくてもいい変数は8ビットに
・データを1ドットあたり1byte → 1bitとした
・for文を使わず、配列の添え字を変数にせず、すべて展開
  (横1ドットにつきプログラム1行)
などで、横128ドットまでは行きついた。
同期をなんとかせねば。
cap_ntsc_i_412_128.jpg

[2023/11/03]
ジッター(揺らぎ)の原因がプログラムの問題なのか、クリスタルの有無の問題なのか、SYNCとVIDEOと2本の抵抗を使ってATmega328のArduinoに移植してみた。
1ドット毎の幅が違うから右端がそろわないけど、くっきりになった。
cap_ntsc_i_412_m328p.jpg
やっぱりクリスタルがないとダメってことか。

[2023/11/03]
いろいろ修正しながらATtint202でやってみた。
ジッター(揺らぎ)はあるものの、くっきりはした。エッジがぼやけるのはDACのせいだったらしい。
cap_ntsc_i_202.jpg
もうちょっと形になったらブログに上げたい。

nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。