/***********************************************************************/
/* */
/* 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;
}