TV出力実験

PSoCEval1でTV出力(NTSCのモノクロ出力)ができないか実験してみました。
http://nicotak.com/psoc/sample/
eval1_tvout.zip



回路図です。抵抗2本とビデオの端子をつないだだけで作れます。
P00はPWM16の出力をDigInvで論理を反転させてポートに出力してます。
ポートP00の出力設定はstrongです。


実行したみた結果ですが、、、
横に4ドット出したら終わってしまいました。
処理スピードが足りません。

このマイコンは24MHzなんですが、どういうわけかAVRの8MHzよりも遅いみたいです。
これは最適化とかアセンブラとかでどうにか速くなるんでしょうか。
というわけで、まだまだ実験中です。


プログラムです。
簡単に説明すると次のとおりです。
・15750Hz周期で割り込みをかける。
・ライン数を1からカウントする。
・ライン数が262になったら1画面終了、1に戻す。
・ライン数が22以上だと描画。それ未満は同期信号です。
・60画面ぶんで1秒が経過。

//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------
#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules

int linenum = 0;
int tick=0;

unsigned int vram[]={
0b0100010001000100,
0b1010101010101010,
0b1110111011101110,
0b1010101010101010,
0b0000000000000000,
0b1100110011001100,
0b1010101010101010,
0b1100110011001100,
0b1010101010101010,
0b1100110011001100,
0b0000000000000000,
0b0110011001100110,
0b1000100010001000,
0b1000100010001000,
0b1000100010001000,
0b0110011001100110,
};

#define WIDTHSYNC  (12000000/1000000)
#define WIDTHSYNC2 (12000000/160000)
#define PWMPERIOD  (12000000/15750)

char video_row=0;
char video_row0=0;
char dotcnt=0;
unsigned int video_dotdat=0x0000;
unsigned int video_dotmsk;

#define VIDEO_ROWMAX 16
#define VIDEO_DOTH 10
#define VIDEO_SYSCLINE 22

#pragma interrupt_handler pwmISR
void pwmISR(void){

	linenum++;
	if(linenum < VIDEO_SYSCLINE){
		if(linenum == 7){	//7-21
		    PWM16_WritePulseWidth(WIDTHSYNC2);  
			video_row=0;	
			video_row0=0;	
		}
		if(linenum == 1){	//1-6
		    PWM16_WritePulseWidth(PWMPERIOD-WIDTHSYNC);  
		}
		return;
	}
	if(linenum >= ((VIDEO_ROWMAX*VIDEO_DOTH)+VIDEO_SYSCLINE)){
		if(linenum==262){
			linenum=0;
			tick++;
		}
		return;
	}

	video_dotdat = vram[video_row];
	dotcnt=4;
	while(dotcnt--){
		if(video_dotdat & 0x8000){
			PRT1DR |= (1<<0);// Port 1 Data Register
		}else{
			PRT1DR &= ~(1<<0);// Port 1 Data Register
		}
		video_dotdat <<=1;
	}
	PRT1DR &= ~(1<<0);// Port 1 Data Register

	video_row0++;
	if(video_row0 >= VIDEO_DOTH){
		video_row0=0;
		video_row++;
	}
}

void main()
{
	int tickbak=0;
	char f=0;
	int sec=0;
	
    /* set period to eight clocks */  
    PWM16_WritePeriod(PWMPERIOD-1);  
  
    /* set pulse width to generate a duty cycle */  
    PWM16_WritePulseWidth(WIDTHSYNC2);  
	
	LCD_Start();
	PRT1DM0 |=  (1<<0);  // Port 1 Drive Mode 
	PRT1DM1 &= ~(1<<0);  // Port 1 Drive Mode 
	PRT1DM2 &= ~(1<<0);  // Port 1 Drive Mode 

	M8C_EnableGInt;//Enable Global Interrupt
    PWM16_Start();    /* start the PWM8! */  
    PWM16_EnableInt();  
	DigInv_Start();

	while(1){
		while(tickbak==tick);
		tickbak=tick;
		
		f++;
		if(f>=60){	//60f = 1sec
			f=0;
			LCD_Position(0,0);
			LCD_PrHexInt(sec);
			sec++;
		}
	}
}