JR-100のNTSC信号を標準化(4)

JR-100のビデオ出力信号をNTSC規格になるべく従うよう整形すべく、PICマイコンを使って何とかしようという企画の4回目。前回までで開発環境とデバッグ用のプログラムを作るところまではできました。今回はいよいよPICのプログラムを作っていきます。かなり正確な時間のパルス幅を作る必要があるのと、PICのMIPS値が最大でも8MIPSと余裕がなさそうなことから、アセンブラで記述しています。

まずプログラムに行く前に回路図を少し修正します。

修正のポイントは、PICのインサーキットデバッグをするために、同期信号の入力ピンをRA0からRA2に変更したことと、PICkit3の接続用のポートを設けたところ、最後の加算回路に計算用に入れておいた75Ωの抵抗を削除したことです。インサーキットデバッグについてはShigehiro Kimuraさんの記事(⇒MPLABXとPICKit3でPICをデバッグしてみる)を参考にさせていただきました。PIC16F1705の場合のPICkit3との接続は以下のようにします。

PICkit3のピン番号 PIC16F1705のピン番号 ピンの意味
1 4 RA3/MCLR
2 1 VDD
3 14 GND
4 13 RA0/ICSPDAT
5 12 RA1/ICSPCLK
6 使わない 使わない

RA0をデバッグ用に使うため、同期信号の入力を空いているRA2に変更しました。

さてプログラムですがJR-100のNTSC信号を標準化(2)で考えたアルゴリズムをそのまま実装しています。外付け水晶発振子を3.579545MHzのものと8MHzのもので試すため、パラメータのいずれかをコメントアウトして使います。

当初はタイマー2,4,6割り込みをフル活用して同期信号の開始時点を決定していたのですが、割り込み発生時の振り分け処理に多くの命令サイクルを消費してしまうのが厳しいことと、割り込みが発生してから割り込み処理ルーチンに飛んでくるまでの時間(命令サイクル数)が不確定であることから、すべてループを使って適当な時間の待ち時間を発生させるようにしています。なお同期信号を生成している時間以外は何もすることがないので、メインループはただの無限ループです。

 

; PIC16F1705 Configuration Bit Settings
; Assembly source line config statements
#include "p16f1705.inc"

; 3.579545MHz水晶発振子を使用する場合
;  __CONFIG _CONFIG1, _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
;  __CONFIG _CONFIG2, _WRT_OFF & _PPS1WAY_ON & _ZCDDIS_ON & _PLLEN_ON & _STVREN_ON & _BORV_LO & _LPBOR_OFF & _LVP_ON
; COUNT110us  EQU     d'10'
; COUNT047us  EQU     d'5'
; COUNT578us  EQU     d'68'

; 8MHz水晶発振子を使用する場合
 __CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
 __CONFIG _CONFIG2, _WRT_OFF & _PPS1WAY_ON & _ZCDDIS_ON & _PLLEN_ON & _STVREN_ON & _BORV_LO & _LPBOR_OFF & _LVP_ON
COUNT110us  EQU     d'28'
COUNT047us  EQU     d'12'  ; 8MHz
COUNT578us  EQU     d'153'   ; 3.579545MHz

; VSYNCMODE: 同期信号の検出状態
;   0: 垂直同期信号未検出 (初期状態)
;   1: 垂直同期信号を検出したが、映像信号も送出している。
;   2: 垂直同期信号を検出し、映像信号はまだ送出していない。
VSYNCMODE   EQU 0x70

; LINE: フレーム番号
; 0~2: 垂直同期パルス
; 3~16: 垂直ブランキング後縁 (3~5: 後置等化パルス)
; 17~39: 上部余白期間
; 40~231: 映像期間
; 232~252: 下部余白期間
; 253~255: 垂直ブランキング前縁 (前置等化パルス)
LINE        EQU 0x71
        
LOOPCOUNTER EQU 0x72
  
RES_VECT  CODE    0x0000
    GOTO    START

; 割り込み処理ルーチン
ISR     CODE    0x0004              ; 割り込み処理
    ; BSR==0であることを前提とする。
    MOVLB   d'7'
    BTFSS   IOCAF,IOCAF2
    RETFIE
    MOVLB   d'0'
    MOVFW   VSYNCMODE
    SUBLW   h'01'                   ; Z=1ならVSYNCMODE=1, C=1ならVSYNCMODE=0, C=0ならVSYNCMODE=2
    BTFSC   STATUS, Z
    GOTO    VSYNCMODE1
    BTFSC   STATUS, C
    GOTO    VSYNCMODE0

; 256回目の立ち下がりエッジを検出する。
VSYNCMODE2
    INCFSZ  LINE,1
    BRA     VSYNCMODE2__SKIP
    MOVLW   h'01'
    MOVWF   VSYNCMODE
    MOVLW   d'255'
    MOVWF   LINE
VSYNCMODE2__SKIP
    MOVLB   d'7'
    BCF     IOCAF,IOCAF2
    MOVLB   d'0'
    RETFIE

; 水平同期のパルス幅が9.05μs、垂直同期のパルス幅は500.7μsである。
; そこでマージンを含めて11μsの同期信号の状態がLowなら垂直同期と判定する。
VSYNCMODE0
    MOVLW   COUNT110us
    MOVWF   LOOPCOUNTER
VSYNCMODE0__LOOP
    DECFSZ  LOOPCOUNTER,1
    BRA     VSYNCMODE0__LOOP
    NOP
    ; このときのRA2の値がHIGHならHSYNC、LOWならVSYNC
    BTFSS   PORTA,RA2
    BRA     VSYNC_MODE0__SKIP
    ; VSYNC検出
    MOVLW   h'02'
    MOVWF   VSYNCMODE
    MOVLW   d'9'
    MOVWF   LINE
VSYNC_MODE0__SKIP  
    MOVLB   d'7'
    BCF     IOCAF,IOCAF2
    RETFIE

; ライン番号に従って適切な幅の同期パルスを生成する。
VSYNCMODE1
    INCFSZ  LINE,1
    BRA     GENERATE_HSYNC
GENERATE_VSYNC
    MOVLB   d'7'
    BCF	    IOCAP,IOCAP2
    ; line0
    MOVLB   d'0'
    BCF     PORTC,RC0
    MOVLW   COUNT578us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE0_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE0_1
    NOP
    BSF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE0_2
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE0_2
    ; line1
    BCF     PORTC,RC0
    MOVLW   COUNT578us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE1_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE1_1
    NOP
    BSF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE1_2
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE1_2
    ; line2
    BCF     PORTC,RC0
    MOVLW   COUNT578us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE2_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE2_1
    NOP
    BSF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE2_2
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE2_2
    ; line3
    BCF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE3_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE3_1
    BSF     PORTC,RC0
    MOVLW   COUNT578us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE3_2
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE3_2
    NOP
    ; line4
    BCF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE4_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE4_1
    BSF     PORTC,RC0
    MOVLW   COUNT578us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE4_2
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE4_2
    NOP
    ; line5
    BCF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE5_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE5_1
    BSF     PORTC,RC0
    MOVLW   COUNT578us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE5_2
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE5_2
    NOP
    ; line6
    BCF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE6_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE6_1
    BSF     PORTC,RC0
    MOVLW   COUNT578us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE6_2
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE6_2
    NOP
    ; line7
    BCF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE7_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE7_1
    BSF     PORTC,RC0
    MOVLW   COUNT578us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE7_2
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE7_2
    NOP
    ; line8
    BCF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE8_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE8_1
    BSF     PORTC,RC0

    MOVLW   d'8'
    MOVWF   LINE
    MOVLB   d'7'
    BCF     IOCAF,IOCAF2
    BSF     IOCAP,IOCAP2
    MOVLB   d'0'
    RETFIE
GENERATE_HSYNC
    NOP
    BCF     PORTC,RC0
    MOVLW   COUNT047us
    MOVWF   LOOPCOUNTER
GENERATE_VSYNC__LINE_1
    DECFSZ  LOOPCOUNTER,1
    BRA     GENERATE_VSYNC__LINE_1
    BSF     PORTC,RC0
    MOVLB   d'7'
    BCF     IOCAF,IOCAF2
    MOVLB   d'0'
    RETFIE

MAIN_PROG CODE
START
    ; 初期化 - 割り込み
    MOVLB   d'0'
    BSF     INTCON,PEIE
    BSF     INTCON,IOCIE
    ; ポートA
    MOVLB   d'1'
    BSF     TRISA,TRISA2
    MOVLB   d'3'
    CLRF    ANSELA
    MOVLB   d'7'
    BSF     IOCAP,IOCAP2
    ; ポートC
    MOVLB   d'1'
    BCF     TRISC,TRISC0
    MOVLB   d'3'
    CLRF    ANSELC
    
    CLRF    VSYNCMODE
    
    MOVLB   d'0'            ; 以降の処理はすべてBank0のメモリに対して行う。
    BSF     PORTC, RC0      ; 同期信号の初期状態はHigh

    BSF     INTCON,GIE

LOOP
    NOP                     ; 割り込み間隔の安定化のために必要
    BRA     LOOP

    END

いきなり実機で実行したくなる気持ちを抑え、まずはこのプログラムをMPLAB X IDEのシミュレータ機能を使ってデバッグをしてみます。(続く)


関連記事一覧

投稿者: けむしろう

プログラミング、サーバ構築、電子工作、旅行が好きです。

コメントを残す

メールアドレスが公開されることはありません。