/***********************************************************************/
/*                                                                     */
 
/*  FILE        :control_AD9851_12.c                                   */
 
/*  DATE        :Mon, Dec 05, 2005                                     */
 
/*  DESCRIPTION :Main Program                                          */
 
/*  CPU TYPE    :Other                                                 */
 
/*                                                                     */
 
/*  This file is generated by Renesas Project Generator (Ver.4.0).     */
 
/*                                                                     */
 
/***********************************************************************/
#include "sfr_r815.h"
 
 //**********************************************************************
   //for AD9851
 
  #define RESET		p3_4 
  #define D7		p3_3
 
  #define W_CLK		p1_0
 
  #define FQ_UD 	p1_1
 
  #define high		1 
  #define low		0
 
//************************************************************************
void set_timerX(void);
 
void set_terminals(void);		//port設定
 
// for LCD display
 
  #define E			p1_3
 
  #define R_W		p1_2
 
  #define RS		p4_5
 
signed char	pos_former = 0; 
unsigned char	j=0; 
unsigned char	str[10]="";
 
//************************************************************************
//for AD9851 
void set_FastCLK(void);
 
void reset_DDS(void);
 
void send_data(void);
 
float DDS_data;
 
unsigned long data;
 
signed long freq = 1000000; 
signed long former_freq = 0;
 
signed long ex_freq = 1; 
signed long disp_freq=0;
 
signed long offset_temp=455000;
 
unsigned int i;
 
unsigned char index = 0;
 
//*************************************************************************
//for  LCD display
 
void initialize_LCD(void);
 
void lcd_cmd(void);
 
void lcd_data(unsigned char);
 
void busy_check(void);
 
void lcd_write_str(unsigned char* );
 
void lcd_clr(void);
 
void my_sprintf(unsigned long );
 
void set_comma(unsigned long );
 
void locate(unsigned char ,unsigned char);
 
//*************************************************************************
	//for Push_SW
 
#define up		p4_7
 
#define down	p4_6
 
void up_sw_pushed(void);
 
void down_sw_pushed(void);
 
//***************************************************************************
	//for rotary encoder
 
#define A	p3_5
 
#define B	p3_7
 
signed char dir[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,-1,1,0 }; /* 回転方向テーブル */
 
unsigned char result[11]="";
 
//****************************************************************************
//multi関係
unsigned char multi_pos = 3; 
char multi_rev_flag=0;
 
unsigned char change_multi=0;
 
unsigned char config_offset=0;
 
const char str_multi[7][8] 
		= {"x1Hz   ","x10Hz  ","x100Hz ","x1KHz  ","x10KHz ","x100KHz","x1MHz  " };
 
const signed long multi[7] = {1,10,100,1000,10000,100000,1000000};
 
//unsigned reverse_flag=0;
 
//*****************************************************************************
//function 関係
 
const char str_function[4][10] 
		= {"SG mode? ","mem_call ","Cnfg VFO ","2tone?   " };
 
unsigned char function=0;
 
unsigned char func_rev_flag=0;
 
unsigned char release=0;
 
//signed char function_pos = 0;
 
//#define    function           function_array.b0 
//******************************************************************************
//for memory
 
unsigned long memory[10]={1000000,4560000,7890000,0};	//memoryは10個にする。初期値
 
unsigned long offset[10]={0};
 
signed char mem_pos=0;
 
char str_mem_pos[2]="";
 
//****************************************************************************** 
//for simulate
 
//void get_rot_int(void); 
//	シミュレート手順
 
// get_rot_int()を宣言
//	main関数内に、記述
 
//	#pragma interrupt を 除外
//	busy_checkを 除外
//*******************************************************************************
//offset default is minus
 
unsigned char offset_plus =0;
 
void main()
 
{
	drr0=drr1=drr2=drr3=1;	//駆動能力 high
 
	set_FastCLK();
	set_terminals();
	p1=0x00;
	set_timerX();
	initialize_LCD();
	set_terminals();
	if(!down)	//function switch
 
	{
		offset_plus=1;   //offset direction default is minus  offset_plus=0;
 
		locate (1,2);
 
		lcd_write_str("offset is +");
 
		while(!down);
	}
	if(!up)		//桁取りswitch & メモリー選択switch
	{
		dir[13]=+1;		//逆dialに設定
 
		dir[14]=-1;
		locate(1,2);
		lcd_write_str("set to revese dial");
 
		while(!up);
	}
	lcd_clr();
	lcd_write_str("SG ");
 
	locate(1,8);
	set_comma(freq );
 
 	lcd_write_str(result);
	lcd_write_str(" Hz");
 
//桁数移動の初期化
	multi_pos = 3;
 
	set_terminals();
	locate(2,1);
	lcd_write_str( str_multi[multi_pos] );
 
	set_terminals();
	reset_DDS();
	set_terminals();
	DDS_data=28.6334085*freq;//DDS_data=設定値 28.6334082
 
	data=(unsigned long)DDS_data;	//data=DDS_dataを32ビット整数値に変換したもの
 
	send_data();
	asm("FSET I");	//割り込み許可
 
	txs = 1; 				//タイマXカウント制御開始ビットのセット
 
//	get_rot_int(); 
	while(1)
	{
		if(!up)
		{ 
			asm("FCLR I");
 
			up_sw_pushed();
			asm("FSET I");
 
		}
		if(!down)
		{
			asm("FCLR I");
 
			down_sw_pushed();
			asm("FSET I");
 
		}
	}
}
#pragma interrupt /B get_rot_int(vect=22)
 
void get_rot_int()
 
{
	index = ( pos_former<<2 )+ (A<<1) + B;
 
	pos_former = (A<<1) + B;	//今の状態を記憶	Aを上位、Bを下位とする
 
	if( function==0 )	//SG mode
 
		{
			freq += multi[multi_pos] * dir[index];
 
			set_terminals();
			DDS_data=28.6334085*freq;	//DDS_data=設定値 28.6334082
 
			data=(unsigned long)DDS_data;	//data=DDS_dataを32ビット整数値に変換したもの
 
			send_data();
			if( (ex_freq - freq ) != 0 )
 
			{
				set_terminals();
				locate(1,8);
				set_comma(freq );			//10MHzで、0.633mS費やす
 
				lcd_write_str(result);
				ex_freq = freq;
 
			}
		}
	if( function==1 )	//set memory
 
		{
			mem_pos +=dir[index];
 
			if(	mem_pos >= 9 )mem_pos=9;
 
			if( mem_pos <= 0 )mem_pos=0;
 
			str_mem_pos[0] = mem_pos+0x30;
 
			set_terminals();
			locate(1,4);
			lcd_write_str(str_mem_pos);
			set_terminals();
			locate(1,8);
			set_comma(memory[mem_pos] );			//10MHzで、0.633mS費やす
 
			lcd_write_str(result);
			lcd_write_str(" Hz");
 
		}
	if( (function==2) && (change_multi==1)  && (config_offset==0) )	//Config VFO mode
 
		{
			freq += multi[multi_pos] * dir[index];
 
			if(freq <0)freq=0;
 
			if(offset_plus==0)	disp_freq= freq + offset_temp;
 
			else			 	disp_freq= freq - offset_temp;
 
			set_terminals();
			DDS_data=28.6334085*freq;	//DDS_data=設定値 28.6334082
 
			data=(unsigned long)DDS_data;	//data=DDS_dataを32ビット整数値に変換したもの
 
			send_data();
			if( (ex_freq - freq ) != 0 )
 
			{
				set_terminals();
				locate(1,8);
				set_comma( disp_freq );			//10MHzで、0.633mS費やす
 
				lcd_write_str(result);
				ex_freq = freq;
 
			}
		}
	if( config_offset==1 ) 
		{
			offset_temp += multi[multi_pos] * dir[index];
 
			set_comma( offset_temp );			//10MHzで、0.633mS費やす
 
			set_terminals();
			locate(1,8);
			lcd_write_str(result);
		}
}
void up_sw_pushed()			// select multi
 
{
	for(i=0;i<20000;i++);		//チャタリング防止用
 
	if( up ) return;
 
	for(i=0;i<20000;i++);		//チャタリング防止用
 
	if( up ) return;
 
	if(change_multi == 0)
 
	{
		set_terminals(); 
		locate(2,9);
		lcd_write_str("          ") ; 
	}
	if( (function==0 ) || ( change_multi==1) )
 
	{
		if(multi_pos ==6) multi_rev_flag = 1;
 
		if(multi_pos ==0) multi_rev_flag = 0;
 
		if(multi_rev_flag) multi_pos--;
 
		else               multi_pos++;
 
		set_terminals();
		locate(2,1);
		lcd_write_str( str_multi[multi_pos] );
 
		if( function ==2 )
 
		{
			if(offset_plus==0)	lcd_write_str("-");
 
			else    			lcd_write_str("+");
 
		}
	}
	if( function==1 ) 
	{
		freq =memory[mem_pos];
 
		locate(1,1);
		lcd_write_str("SG  ");
 
		function=0;
	}
	while(!up);
}
void down_sw_pushed()	//down_SWで、functionを決定する
 
{
	for(i=0;i<20000;i++);		//チャタリング防止用
 
	if( down ) return;
 
	for(i=0;i<20000;i++);		//チャタリング防止用
 
	if( down ) return;
 
	if(	function==3 )func_rev_flag=1;
 
	if( function ==0)func_rev_flag=0;
 
	if(change_multi == 0)
 
	{
		if(	func_rev_flag )function--;
 
		else  		       function++;
 
		set_terminals();
		locate(2,9);
		lcd_write_str( str_function[function] );
 
	}
	if( function==0)
 
	{
		lcd_clr();					//SGモード表示
 
		locate(1,1);
		lcd_write_str("SG ");
 
		set_terminals();
		locate(1,8);
		set_comma(freq );			//10MHzで、0.633mS費やす
 
		lcd_write_str(result);
		lcd_write_str(" Hz");
 
	}
	if( function==1) 
	{
		lcd_clr();					//Memモード表示
 
		locate(1,1);
		lcd_write_str("Mem");
		former_freq=freq;
	}
	if( (function==2) && (change_multi==1) && (release==1) )
 
	{
		change_multi = 0; 	//config VFO mode 解除
 
		release = 0;
 
		memory[mem_pos]=freq;
		offset[mem_pos]=offset_temp;
		freq = former_freq;
 
		function=0;
		set_terminals();
		lcd_clr();
		locate(1,8);
		set_comma(freq );			//10MHzで、0.633mS費やす
 
		lcd_write_str(result);
		lcd_write_str(" Hz");
 
		locate(1,1);
		lcd_write_str("SG  ");
 
	}
	if( (function==2) && (change_multi==1) && (release==0) )
 
	{
		config_offset=0;
		release=1;
		freq = offset_temp;
 
		lcd_clr();					//VFOモード表示
 
		str_mem_pos[0] = mem_pos+0x30; 
		set_terminals();
		locate(1,1);
		lcd_write_str(str_mem_pos);
		locate(1,3);
		lcd_write_str("VFO");
		set_terminals();
		locate(2,8);
		set_comma( offset_temp );
 
		lcd_write_str(result);
		lcd_write_str(" Hz");
 
		locate(2,7);
		if(offset_plus==0)	lcd_write_str("-");
 
		else    			lcd_write_str("+");
 
		set_comma(disp_freq);		//ここ、何とかならんか?
 
		locate(1,8);
		lcd_write_str(result);
		lcd_write_str(" Hz");
 
	}
	if( (function==2) && (change_multi==0)  && (config_offset==0) )	//offset config
 
	{
		config_offset=1;
		change_multi=1;
		former_freq=freq;
		set_terminals();
		locate(1,1);
		lcd_write_str("ofs?");
		freq = offset_temp;
 
		set_comma(offset_temp);
		locate(1,8);
		lcd_write_str(result);
		lcd_write_str(" Hz");
 
	}
	while(!down); 
}
void set_FastCLK(void)
 
{
	prc0=1;
	hra00=1;
	cm06=0;
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop");
	hra01=1;
	ocd2=1;
	prc0=0;
}
	//for AD9851
 
void set_terminals()
 
{
	//出力に設定
	pd1=0xFF;
	pd3_3=pd3_4=pd4_5=1;
	pd3_5=pd3_7=0; 			//for rotary encoder
 
	//入力に設定 (ハードで、Pull_Upされている)
	//pd4_6=pd4_7=0;		不要なり
 
}
void reset_DDS()
 
{
	RESET=high;		//RESET
 
	for(i=0;i<13000;i++);
	RESET=low;
	W_CLK=high;		//serial設定
 
	W_CLK=low;
	FQ_UD=high;
	FQ_UD=low;
}
void send_data()
 
{
	for(i=0;i<32;i++)
		{
			if(data & 0x01) D7=high;
 
			else          		 D7=low;
 
			W_CLK=high;
			W_CLK=low;
			data=data >>1;
 
		}
	D7=high;		//クロック6倍モード指定
 
	W_CLK=high;
	W_CLK=low;
	D7=low;		//logic 0
 
	W_CLK=high;
	W_CLK=low;
	D7=low;		//power down=no
 
	W_CLK=high;
	W_CLK=low;
	for(i=0;i<5;i++)	//位相制御 位相=0;
		{
			D7=low;
			W_CLK=high;
			W_CLK=low;
		}
	FQ_UD=high;
	FQ_UD=low;
}
		//for LCD
 
void initialize_LCD()
 
{ 
	for(i=0;i<13000;i++);		//21mS
 
	p1=0x30;						//DB7-4 0011
 
	R_W=0;
	RS=0;
	E=1;
	asm("nop");	//need 0.4uS OK?     simulate 0.5uS OK
 
	asm("nop");
	asm("nop");
	asm("nop"); 
	asm("nop");
	E=0;
	for(i=0;i<6300;i++);			//10.2mS
 
	p1=0x30;						//DB7-4 0011
 
	R_W=0;
	RS=0;
	E=1;
	asm("nop");	//need 0.4uS OK?     simulate 0.5uS OK
 
	asm("nop");
	asm("nop");
	asm("nop"); 
	asm("nop");
	E=0;
	for(i=0;i<200;i++);			//over 200uS
 
	p1=0x30;						//DB7-4 0011
 
	R_W=0;
	RS=0;
	E=1;
	asm("nop");	//need 0.4uS OK?     simulate 0.5uS OK
 
	asm("nop");
	asm("nop");
	asm("nop"); 
	asm("nop");
	E=0;				//set 8bit interface
 
	busy_check(); 
	p1=0x20;						//DB7-4 0010
 
	lcd_cmd();					//set interface to 4-bit
 
	busy_check(); 
	p1=0x20;						//2lines 5x7 character	Function set 
	lcd_cmd();
	p1=0x80;
	lcd_cmd();
	busy_check();
	p1=0x00;						//Display off
 
	lcd_cmd(); 
	p1=0x80;
	lcd_cmd();
	busy_check();
	p1=0x00;						//clear Display
 
	lcd_cmd();
	p1=0x10;
	lcd_cmd();
	busy_check();
	p1=0x00;						//Entry mode set
 
	lcd_cmd();
	p1=0x60;						//DB7-4=0110
 
	lcd_cmd();
	busy_check();
	p1=0x00;						//Display ON 
	lcd_cmd();
	p1=0xC0;				   //DB7-4=1110  cursol off no blink 
//	p1=0xE0;				   //corsor on
 
	lcd_cmd();
	busy_check();			//cmdは、busy_checkして終わる事
 
}
void lcd_clr()
 
{
	busy_check();
	p1=0x00;						//clear Display
 
	lcd_cmd();
	p1=0x10;
	lcd_cmd();
	busy_check();
}
void lcd_cmd()
 
{
	R_W=0;
	RS=0;
	E=1;
	asm("nop");	//need 0.4uS OK?     simulate 0.5uS OK
 
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop"); 
	E=0;
}
void busy_check()
 
{
unsigned char test_bit=0;
 
	pd1=0x0F;	//port1 DB7-4 direction = read
 
check:
	R_W=1;	//read
 
	RS=0;
	E=1;
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop");
	E=0;
	test_bit=p1;		//上位ビットの取り込み
 
	R_W=1;	//read
 
	RS=0;
	E=1;
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop");
	asm("nop");
	E=0;
	//p1=下位ビットは、取り込み だけで、使わない
 
	test_bit=test_bit>>7;
	if( test_bit  ) goto check;
 
	pd1=0xff;		//p1 DB7-4 direction = write 
}
void lcd_data( unsigned char c)
 
{
	p1 = c;		//上位送信
 
	R_W=0;
	RS=1;
	E=1;
	asm("nop"); 
	asm("nop");
	asm("nop");
	asm("nop"); 
	asm("nop");
	E=0; 
	p1=(c<<4);				//下位送信
 
	R_W=0;
	RS=1;
	E=1;
	asm("nop"); 
	asm("nop");
	asm("nop");
	asm("nop"); 
	asm("nop");
	E=0; 
	busy_check();		//check busy_check
 
}
void lcd_write_str(unsigned char* c)
 
{
	pd1=0xff;		//p1 DB7-4 direction = write 
		while(*c !=0x00)
 
			{
				lcd_data(*c);
				c++;
			}
}
void my_sprintf(unsigned long x)
 
{
	char z_flag=1;	//このフラグがゼロ以降は、空白に変わらないで数字のゼロを表示
 
	//ここで、reverseされた 文字列が、出来上がる
	for(i=0;i<10;i++)
	{
		*(str + i) = (x % 10) + 0x30;
 
		x = x /10;
 
	}
	//ここで、上位のゼロを、空白に変える
	for(i=0;i<10;i++)
	{
		if( *(str + 9 - i) != 0x30) z_flag=0;
 
		if( (z_flag) && *(str + 9 - i) ==0x30  )	*(str + 9 -i) =0x20;
 
	} 
}
void set_comma(unsigned long  x)		//simulate=417uS
 
{
	my_sprintf(x);
	j=0;
	for (i=0;i<10;i++)
 
		{
			*(result + 9 - j) = *(str + i);
 
			if( ( (i % 3) == 2 ) && ( i !=0  ) && ( *(str + i+1) != 0x20) )
 
			{
				j++;
				*(result + 9 - j) = '.';
 
			}
			j++;
		}
}
void locate(unsigned char gyou ,unsigned char retsu)
 
{
	char reserv_p1;		// Eの為に、p1の下位の値が、狂う!
 
	reserv_p1 = p1 = 0x80 + (gyou - 1)*0x40 + retsu-1  ;
 
	lcd_cmd();
	p1 = reserv_p1<<4;
 
	lcd_cmd();
	busy_check();		//必ずbusy_checkして終わる
 
}
void set_timerX()
 
{
//f8
	txck0 = 1;
 
	txmr = 0;
 
	tx = 44;
 
	prex = 44;
 
	ilvl0_txic = 1;
 
	ir_txic = 0;
 
}