/***************************************************************

160m SSB 送信機コントローラー　for PIC16F1938  Ver 1.2.1
2022年04月28日 

周波数設定範囲  1800KHz-1875KHz
 * LO2 freq : 16003.937KHz 固定 調整後修正
  LO3 Sub carrir 9.082KHz　調整後修正
XC8 V2.20

PIC16F1938

Si5351A コントロール Lo1

電源電圧表示
*PTT SW チャタリング対応、ロータリーエンコーダのタイミング1mSECを4mSECに変更 V1.2.1
*last周波数の記録が時々ずれるバグを修正 V1.2.1

 ********************************************************************/

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>


#define _XTAL_FREQ 16000000


#define SI5351_I2C_ADDR     0xc0

//#define SI5351_XTAL_FREQ    24999633
#define SI5351_XTAL_FREQ    24999646//誤差0.1Hz
#define SI5351_PLL_FREQ     900000000

#define SI5351_OUTPUT_CTRL  3
#define SI5351_CLK0_CTRL    16
#define SI5351_CLK1_CTRL    17
#define SI5351_CLK2_CTRL    18
#define SI5351_PLL_A        26 //LO1
#define SI5351_PLL_B        34 //LO2
#define SI5351_MS_0         42
#define SI5351_MS_1         50
#define SI5351_MS_2         58  //	未使用
#define SI5351_PLL_RESET    177
#define SI5351_XTAL_LOAD    183

#define LCD_PORT PORTA	// set LCD port */
#define LCD_E LATCbits.LATC1		/* set E bit of I/O port */
#define LCD_RS LATAbits.LATA3		/* set RS bit of I/O port */
#define LCD_CMD 0
#define LCD_DAT 1
#define LED LATBbits.LATB5

#define PTTsw PORTCbits.RC5 //PTT sw入力 0:SEND 1:RX
#define TXEN LATBbits.LATB1 //送信出力ポート　１：送信　０：受信
//#define RXEN LATBbits.LATB0 //受信出力ポート　0：送信　1：受信
#define REA1 PORTBbits.RB7   //ロータリーエンコーダー１A端子
#define REB1 PORTBbits.RB6   //ロータリーエンコーダー１B端子
#define KEYIN PORTCbits.RC0  //Key in keydown:L
#define ADGO ADCON0bits.GO_nDONE //ADC START/DONE
#define DSPRES LATBbits.LATB4 //dsPIC reset
#define MODE0 LATBbits,LATB2 
#define MODE1 LATBbits,LATB3 
#define SPANLED LATCbits.LATC6 //span freq 1K ON
#define KEYDWN LATCbits.LATC7 //Key down(Mark):H) output keyinに対して遅延有り

#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = ON, MCLRE = ON, CP = OFF, CPD = OFF
#pragma config BOREN = OFF, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF
#pragma config WRT = OFF, VCAPEN = OFF, PLLEN = OFF, STVREN = OFF, BORV = HI, LVP = OFF


unsigned long int TUNEfreq,lastTUNEfreq,maxTUNEfreq,minTUNEfreq;
unsigned long int Rit0freq,CWoffset;
unsigned long int LO1freq,LO2freq,IF2freq,IF1freq; //　第1局発(可変)、第2局発、第2IF、第1IF
char lcd_data[16];
unsigned char lastPTTsw,SENDflg,lastSENDflg,MODE,lastKEYIN;
unsigned char Ritflg,lastRitflg,dispflg,saveflg,Sdisp;
unsigned long int Fspan,Fs1K;
unsigned long int RITfreq,lastRITfreq;
unsigned int AGCdata,AGCv,lastAGCdata,AGCdelay,SMtcount,SMdelaylimit,lastSLVL,SLVL,SMdata;
signed char lastRE,lastsw0;	
unsigned int SAVEcnt,BKtime,Vdisptime,Vdisptimelimit;
static signed char RE_table[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
unsigned char CWtone[]={32,39,45,50,53,54,53,50,45,39,32,25,19,14,11,10,11,14,19,25};
unsigned char CWindex = 0;
unsigned char CWtoneFlg;
 void i2c_init();
 void i2c_start();
 void i2c_stop();
 void i2c_write(unsigned char byte);
 void si5351_write(unsigned char reg, unsigned char data);
 
 void si5351_init();
 void si5351_setpll(unsigned char pll, unsigned char a, unsigned long b, unsigned long c); // PLL逓倍比設定
 void si5351_setms(unsigned char synth, unsigned long div); // Multisynth分周比設定
 void si5351_setfreq(unsigned char channel,unsigned long freq); // si5351への周波数書込み
void dispRITfreq();
void displaymode(unsigned char m);

 void i2c_start() {
	SSPCON2bits.SEN = 1;
	while(SSPCON2bits.SEN);
	}


 void i2c_stop() {
	SSPCON2bits.PEN = 1;
	while(SSPCON2bits.PEN);
	}

 void i2c_write(unsigned char byte)  {
	PIR1bits.SSPIF = 0;
	SSPBUF = byte;
	while(!PIR1bits.SSPIF);
	SSPCON1bits.CKP = 1;
	}

//***********************************************************************************

void initmain() {
	OSCCON = 0x78;//0b01111000; // INTOSC 16MHz
    OPTION_REG = 0x97;//0b10010111;
    TRISC = 0x39;//0b00111001;//RC0,5 input RC3,4 i2c input　RC2 PWMout RC1:LCD E
    PORTC = 0x00;//0b00000000;
	TRISA = 0x07;//0b00000111;//RA0,1,2 input
	TRISB = 0xC0;//0b11000000;//RB6,7 RE用inputに設定  RB5 LED
	PORTA = 0x00;//0b00000000;
	PORTB = 0x00;//0b00000000;//RB4は０でスタート

//ADC設定	
	ANSELA = 0x07;//0b00000111;// AD AN0,1,2使用
	ANSELB = 0x00;//0b00000000;// 
	ADCON0 = 0x0D;//0b00001101; // AN3 only
    ADCON1= 0xA0;//0b10100000	; //右詰め　ADCS 1/32 Vref=VDD


// I2C設定
	SSPCON1 = 0x28;// 0b00101000;  // I2C master mode, Clock 400kHz = Fosc / ( 4 * (SSPADD + 1 ))
	SSPSTAT = 0x00;//0b00000000;  // Slew rate control Enabled
	SSPADD = 0x09;//0b00001001;  // _XTAL_FREQ / (SSPADD + 1) * 4 = 400khz

   INTCON = 0x40;//0b01000000;//TMR2,4 割込みOK
	T2CON = 0x07;//0b00000111;//ポストスケーラ1/1に変える事　TMR2ON プリスケーラ　1/64
    TMR2 = 0;//初期設定
    PR2 = 250;// 16usecでカウントUP:125にて2msec間隔
    TMR2ON = 1;
//    TMR2IE = 1;//mainのループ前でON
	TMR2IF = 0;
    
    T4CON = 0x06;//0b00000010;//ポストスケーラ1/1に変える事　TMR4ON プリスケーラ　1/16
    TMR4 = 0;//初期設定
    PR4 = 16;// 4usecでカウントUP:16にて64usec間隔 CW tone 781Hz
    TMR4ON = 1;
    TMR4IE = 0;
	TMR4IF = 0;

//PWM出力設定
	TRISCbits.TRISC2 = 1;//仮にCCP1出力を無効化
    CCPTMRS0bits.C1TSEL=2;//CCP1 Timer6使用
	PR6 = 127;
	CCP1CON = 0x0E;//0b00001110; // active Low 
	CCPR1L = 64;
	T6CON = 0b00000100;//pre:1/1 post 1/1　Timer6スタート
	PIR3bits.TMR6IF = 0;
	TRISCbits.TRISC2 = 0;//CCP1ピン有効
	

	
    GIE = 1;//全割り込み許可
	
}

//EEPROM読み込み
unsigned char eepdata_read(unsigned char adr) {
      unsigned char data;   
      EEADR = adr;//アドレス 0-255
      EECON1 = 0;
      EECON1bits.RD = 1;
      while(EECON1bits.RD == 1);
      data = EEDATA;
      return data;
 }
//EEPROM書き込み
 void eepdata_write(unsigned char adr,unsigned char data) {
      INTCONbits.GIE = 0;
      EEADR = adr;
      EEDATA = data;
      EECON1 = 0;
      EECON1bits.WREN = 1;
      EECON2 = 0x55;
      EECON2 = 0xAA;
      EECON1bits.WR = 1;
      while(EECON1bits.WR == 1);    
      INTCONbits.GIE = 1;
}


void readlastdata() {
	unsigned long int temp0,temp1;
	temp0 = eepdata_read(3);
	temp0=temp0 << 8;temp1 = eepdata_read(2);temp0 = temp0 | temp1;
	temp0=temp0 << 8;temp1 = eepdata_read(1);temp0 = temp0 | temp1;
	temp0=temp0 << 8;temp1 = eepdata_read(0);TUNEfreq = temp0 | temp1;
	MODE = eepdata_read(4);
    Fs1K = eepdata_read(6);

}



void save_TUNEfreq(unsigned char adr,unsigned long int freq) {
	unsigned long int temp0;
	temp0 = freq >> 24; eepdata_write( adr+3, temp0);
	temp0 = 0x00FF0000 & freq;temp0 = temp0 >> 16;eepdata_write( adr+2, temp0);
	temp0 = 0x0000FF00 & freq;temp0 = temp0 >> 8;eepdata_write( adr+1, temp0);
	temp0 = 0x000000FF & freq;eepdata_write( adr, temp0);
}


//*************************************************************************************



void si5351_write(unsigned char reg, unsigned char data)
{
    i2c_start();
    i2c_write(SI5351_I2C_ADDR);
    i2c_write(reg);
    i2c_write(data);
    i2c_stop();
}

void si5351_init() {
	si5351_write(3, 0xFF); // Reg. address 3d(Output Enable Control), All output disable
	si5351_write(16, 0x80); // Reg. address 16d (CLK0 Control), CLK0 power down
	si5351_write(17, 0x80); // Reg. address 17d (CLK1 Control), CLK1 power down
	si5351_write(18, 0x80); // Reg. address 18d (CLK2 Control), CLK2 power down
    si5351_write(SI5351_XTAL_LOAD, 0x80);   // 8pF
}

void si5351_setpll(unsigned char pll, unsigned char a, unsigned long b, unsigned long c)
{
    unsigned long P1;
    unsigned long P2;
    unsigned long P3;

    P1 = 128 * a + (unsigned long)(128 * (float)b / c) - 512;
    P2 = 128 * b - c * (unsigned long)(128 * (float)b / c);
    P3 = c;
    
    si5351_write(pll,     (P3 & 0x0000FF00) >> 8);
    si5351_write(pll + 1, (P3 & 0x000000FF));
    si5351_write(pll + 2, (P1 & 0x00030000) >> 16);
    si5351_write(pll + 3, (P1 & 0x0000FF00) >> 8);
    si5351_write(pll + 4, (P1 & 0x000000FF));
    si5351_write(pll + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
    si5351_write(pll + 6, (P2 & 0x0000FF00) >> 8);
    si5351_write(pll + 7, (P2 & 0x000000FF));
}

void si5351_setms(unsigned char synth, unsigned long div)
{
    unsigned long P1;
    unsigned long P2;
    unsigned long P3;

    P1 = 128 * (unsigned long)div - 512;
    P2 = 0;
    P3 = 1;

    si5351_write(synth,     (P3 & 0x0000FF00) >> 8);
    si5351_write(synth + 1, (P3 & 0x000000FF));
    si5351_write(synth + 2, ((P1 & 0x00030000) >> 16));
    si5351_write(synth + 3, (P1 & 0x0000FF00) >> 8);
    si5351_write(synth + 4, (P1 & 0x000000FF));
    si5351_write(synth + 5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
    si5351_write(synth + 6, (P2 & 0x0000FF00) >> 8);
    si5351_write(synth + 7, (P2 & 0x000000FF));
}

void si5351_setfreq(unsigned char channel, unsigned long freq)
{
    unsigned long div;        // synth divider value
    unsigned long pllfreq;    // target PLL frequency
    unsigned char a;        // multisynth a
    unsigned long b;        // multisynth b
    unsigned long c;    // multisynth c
    unsigned long lltmp;    // temporary value

    div = SI5351_PLL_FREQ / freq;     
    div = div >> 1;                // synth divider value is even integer
    div = div << 1; 
    pllfreq = div * freq;            
    c = 0xfffff;                // 20bit denominator max value 
    a = pllfreq / SI5351_XTAL_FREQ;    
    lltmp = pllfreq % SI5351_XTAL_FREQ;
    b  = lltmp * ((float)c / SI5351_XTAL_FREQ);
  
    si5351_write(SI5351_OUTPUT_CTRL, 0xff);

    
    if(channel == 0) {
        si5351_setpll(SI5351_PLL_A, a, b, c);
        si5351_setms(SI5351_MS_0, div);
           
        si5351_write(SI5351_CLK0_CTRL, 0x4f);
        si5351_write(SI5351_PLL_RESET, 0x20); 
    } else {
         si5351_setpll(SI5351_PLL_B, a, b, c);
        si5351_setms(SI5351_MS_1, div);
           
        si5351_write(SI5351_CLK1_CTRL, 0x6f);
        si5351_write(SI5351_PLL_RESET, 0x80); 
    }
    si5351_write(SI5351_OUTPUT_CTRL, 0xFC);//CLK0:FE CLK0,1:FC CLK0,2:F8 
}
 






void lcd_strobe() {//LCD E ストローブ
    LCD_E = 1;
    __delay_us(2);
    LCD_E = 0;
}

void Putc_LCD(char c, char rs) {
    unsigned char s;
    __delay_us(52); /* >40us */
    LCD_RS = rs;
    s = LCD_PORT & 0x0f;
    LCD_PORT = ((c & 0xf0) + s); /* E=0, RS=rs, high addr */
    lcd_strobe();
    LCD_PORT = ((c << 4) + s); /* E=0, RS=rs, low addr */
    lcd_strobe();
}

void Init_LCD() {//LCDイニシャライズ

    __delay_ms(15);
    LCD_PORT = 0x30; /* E=0, RS=0, command=0x30 */
    lcd_strobe();
    __delay_ms(5); /* > 4.1ms */
    lcd_strobe();
    __delay_us(128); /* >100us */
    lcd_strobe();
    __delay_us(128);
    /* set 4bit mode */
    LCD_PORT = 0x20; /* E=0, RS=0, command=0x20 */
    lcd_strobe();
    Putc_LCD(0x28, LCD_CMD); /* display mode */
    Putc_LCD(0x0C, LCD_CMD); /* display on */
    Putc_LCD(0x01, LCD_CMD); //LCD クリアー
    __delay_ms(10);
    Putc_LCD(0x06, LCD_CMD); /* entry mode */

}

void Puts_LCD(char *ptr) {//文字列を表示
    while (*ptr) {
        Putc_LCD(*ptr++, LCD_DAT);
    }
}

void Set_Pos(unsigned char x) {//1行目左端：0　2行目左端：40
    Putc_LCD(((x)&0x7F) | 0x80, LCD_CMD);
}




/***************************************
 * int整数をASCII文字に変換
 ****************************************/
void itostring(char digit, unsigned long int data, char *buffer) {
    char i;

    buffer += digit;
    *buffer = 0; // 最後の数字位置
    for (i = digit; i > 0; i--) { // 変換は下位から上位へ
        buffer--; // ポインター１
        *buffer = (data % 10) + '0'; // ASCIIへ
        data = data / 10; // 次の桁へ
    }
}

void strset(char *as, char *buf) {//文字列をLCD表示用ASCII文字に変換
    while (*as) *buf++ = *as++;
    *buf = 0x00;
}


/////////////////////////////// ADconv
unsigned int adconv(unsigned char c) {
     unsigned int vadc;
    
	ADRESH = 0;
	ADRESL = 0;
	if (c == 0) {return 0;}
	if (c == 1) {ADCON0 = 0x01;}//0b00000001; //AN0 AD変換設定 SW
	if (c == 2) {ADCON0 = 0x09;}//0b00001001; //AN2 AD変換設定 DCV
	
	 __delay_us(100) ;
	ADGO = 1;  			//AD変換開始
   	while(ADGO) ;		// AD変換完了まで待つ
   	vadc = ADRESH ; 	 	// ADRESHの読み取り
   	vadc = ( vadc << 8 ) | ADRESL ; // ADRESLを下位につなぐ
    return vadc;
}
////////////////////////////////////////////////////////////
void dspreset() {
//    __delay_ms(1);
	DSPRES = 1;
	__delay_ms(2);
	DSPRES = 0;
		
}





void setSPAN() {
 	if (Fs1K == 0) {
        Fs1K = 1;SPANLED = 1;
 		TUNEfreq = (TUNEfreq /1000)*1000;
        } else {
        Fs1K = 0;SPANLED = 0;
        }  
	saveflg = 1;SAVEcnt = 0;
}


void displaymode(unsigned char m) {
    Set_Pos(0x0D);
	switch(m) {
	case 0: strset("LSB", lcd_data);Puts_LCD(lcd_data);break;
	case 1: strset(" CW", lcd_data);Puts_LCD(lcd_data);break;
    case 2: strset(" AM", lcd_data);Puts_LCD(lcd_data);break;

	}
}	



void setMODE() {

	if (MODE > 2) {MODE = 0;}
	switch(MODE) {
		case 0: MODE0=1;MODE1=0;displaymode(0);break;//LSB
		case 1: MODE0=0;MODE1=1;displaymode(1);break;//CW
		case 2: MODE0=1;MODE1=1;displaymode(2);break;//AM

	}

__delay_ms(1);
    dspreset();
	saveflg = 1;SAVEcnt = 0;
}

unsigned char getSWnumber(unsigned int vadc) {
	if ((vadc <= 896) && (vadc >640)) {return 1;}
	if ((vadc <= 640) && (vadc >383)) {return 2;}
	if ((vadc <= 383) && (vadc >131)) {return 3;}	
	if (vadc <= 131) {return 4;}
    return 0;
}
unsigned char checkKeySW() {
	unsigned int vadc;
	unsigned char sw0,sw1;//SWナンバー
	vadc = adconv(1);
	sw0 = getSWnumber(vadc);
    if (sw0 == 0) {lastsw0 = 0;return 0;}
    __delay_ms(30);
	vadc = adconv(1);
    sw1 = getSWnumber(vadc); 
    if (sw1 == 0) {lastsw0 = 0;return 0;}
    __delay_ms(30);
    vadc = adconv(1);
    sw0 = getSWnumber(vadc);
    if (sw0 == 0) {lastsw0 = 0;return 0;}
   if (sw0 == lastsw0) {return 0;}
   if (sw0 != sw1) {return 0;} 
		switch(sw0) {
            case 0: return 0;
            case 1: setSPAN();break;//Fspan 変更
 //           case 2: setRIT();break;//RIT
//			case 3: RITclear();break;//RITクリア
			case 4: MODE++;setMODE();break;//LSB-CW-AM
		}
        lastsw0 = sw0;
        return sw0;
}


	


void checkDCV() {
	unsigned int dcv0,dcv1;
	dcv0 = adconv(2);
	// 27k/5.6KのATT時、12Vは2.06Vに変換される。
	dcv0 = dcv0*20/105;
	dcv1= dcv0/10;
	dcv0= dcv0 - dcv1*10;
	strset(". V",lcd_data);
	Set_Pos(0x48);
    Puts_LCD(lcd_data);
    itostring(2, dcv1, lcd_data); 
    Set_Pos(0x46);
    Puts_LCD(lcd_data);
	itostring(1, dcv0, lcd_data); 
    Set_Pos(0x49);
    Puts_LCD(lcd_data);
   	
	
}
void freqdisp(unsigned long int fq) {
    char dg;
	long int F0,F1,F2;

    F0 = fq;
    F2 = F0/1000000;//MHz部分
    F0 = F0-(F2*1000000);//KHz以下 F0=F0%1000000
	F1 = F0/1000;//KHz部分
	F0 = F0-(F1*1000);//Hz部分 F0=F0%1000
    strset("  ", lcd_data);
    Set_Pos(0x00);
    Puts_LCD(lcd_data);
	if (F2 < 10) {dg = 1;} else {dg = 2;}
    itostring(dg, F2, lcd_data); //MHzをASCIIに変換
    Set_Pos(0x02 - dg);
    Puts_LCD(lcd_data);
    strset(".", lcd_data);
    Set_Pos(0x02);
//    Puts_LCD(lcd_data);
	itostring(3, F1, lcd_data); //KHzをASCIIに変換
    Set_Pos(0x02);
    Puts_LCD(lcd_data);

    strset(".",lcd_data);
    Set_Pos(0x05);
    Puts_LCD(lcd_data);
    itostring(3, F0, lcd_data); //HzをASCIIに変換
    Set_Pos(0x06);
    Puts_LCD(lcd_data);
	strset("KHz",lcd_data);
    Set_Pos(0x09);
    Puts_LCD(lcd_data);
    dispflg = 0;

}





//*******************************************************************************
// *  InterFunction()   割り込みの処理                                            *
// *******************************************************************************/

	
	void __interrupt() InterFunction(void) {
    unsigned char k,bf;          
    signed char curRE;
   
	if (TMR4IF == 1) {
		TMR4IF = 0;
		CCPR1L = CWtone[CWindex];
		CWindex++;
        if (CWindex == 20) {CWindex = 0;}
		if (CWtoneFlg == 0) {
			if (CWindex == 0) {
				CCPR1L = CWtone[CWindex];
				TMR4IE = 0;
				TMR4ON = 0;
				}
			}
		}
	if (TMR2IF == 1) {
    	TMR2IF = 0;
    	TMR2IE = 0;
    	TMR2ON = 0;
//        SPANLED=1;
        curRE = REA1 * 2 + REB1;    
        lastRE <<= 2;                      
        lastRE |= ( curRE & 0x03 ); 
        k = (RE_table[(lastRE & 0x0F)]);
        if (k == 1) {
          TUNEfreq = TUNEfreq + Fspan; 
        }
        if (k == 255) {
           TUNEfreq = TUNEfreq - Fspan;
        }
		if (TUNEfreq < minTUNEfreq) {TUNEfreq = minTUNEfreq;}
		if (TUNEfreq > maxTUNEfreq) {TUNEfreq = maxTUNEfreq;}

	    TMR2 = 0; 
    	TMR2IE = 1;
    	TMR2ON = 1;
        SMtcount ++;
		BKtime ++;
		SAVEcnt ++;
        Vdisptime ++;
//        SPANLED=0;
	}

}

	
	
	
void main() {	
	unsigned char dummy,tempPTTsw;

	SMtcount = 0;
	initmain();
    Sdisp=checkKeySW();
   
    
    Init_LCD();
	maxTUNEfreq = 1875000;minTUNEfreq = 1800000;
    LO2freq = 16003866;//LO2周波数固定
//	LO2freq = 16003937;//LO2周波数固定
    
    IF2freq = 9082;//サブキャリア周波数
	IF1freq = LO2freq - IF2freq;//第1IF周波数：16MHｚ

    Vdisptimelimit = 500;//電圧表示周期
	readlastdata();
    TXEN = 0;
	if ((TUNEfreq > maxTUNEfreq) || (TUNEfreq < minTUNEfreq)) {
		TUNEfreq = 1850000;//送信周波数可変
		MODE = 0;
        Fs1K = 1;
        save_TUNEfreq(0,TUNEfreq);
        eepdata_write(4,MODE);
        eepdata_write(6,Fs1K);

	}
   

	freqdisp(TUNEfreq);
	lastTUNEfreq = TUNEfreq;

    lastPTTsw = 1;

	lastSENDflg = 0;SENDflg = 0;

	si5351_init();
    LED=1;
	LO1freq = IF1freq + TUNEfreq;
//    LO1freq = 10000000;
	si5351_setfreq(0,LO1freq);//TUNE freq

	freqdisp(TUNEfreq);

	dispflg = 1;
    setMODE();  
 
    if (Fs1K == 0) {Fspan = 20;} else {Fspan = 1000;
        TUNEfreq = (TUNEfreq /1000)*1000;
        SPANLED = 1;
        }
    
	dspreset();
    TMR2IE = 1;

	while(1) {
        if (Fs1K == 0) {Fspan = 20;} else {Fspan = 1000;
        TUNEfreq = (TUNEfreq /1000)*1000;
        }


		if (TUNEfreq != lastTUNEfreq) {
        lastTUNEfreq = TUNEfreq;
			LO1freq = IF1freq + lastTUNEfreq;
			si5351_setfreq(0,LO1freq);
            freqdisp(lastTUNEfreq);
            saveflg = 1;SAVEcnt = 0;dispflg = 1;
		}
		if (PTTsw != lastPTTsw) {
			tempPTTsw = PTTsw;__delay_ms(50);
            
			if (PTTsw == tempPTTsw) {
				if (PTTsw == 0) {SENDflg = 1;} else {SENDflg = 0;}
            	lastPTTsw = PTTsw;
			}
		}
		if (SENDflg != lastSENDflg) {
			if (SENDflg == 1) {//送信の場合

				TXEN=1;//RXEN=0;
            //    __delay_ms(1);
                dspreset();
                } else { //受信の場合
 
                TXEN = 0;//RXEN=1;
                dspreset();
                }
			lastSENDflg = SENDflg;
		}

        if ((SAVEcnt > 500) && (saveflg == 1)) {
        	save_TUNEfreq(0,TUNEfreq);
        	eepdata_write(4,MODE);
            eepdata_write(6,Fs1K);
        	SAVEcnt = 0;saveflg = 0;
        }
        if (SAVEcnt > 3000) {SAVEcnt = 3000;}
        if (Vdisptime > Vdisptimelimit) {checkDCV();Vdisptime = 0;}
        dummy=checkKeySW();

		if ((KEYIN != lastKEYIN) && (MODE == 1)){
        	if (KEYIN == 0) {
                if (TXEN == 0) {TXEN =1;dspreset();
                }
                __delay_ms(17);KEYDWN = 1;BKtime = 0;lastKEYIN =KEYIN;
            } 
			if (KEYIN == 1) {__delay_ms(17);KEYDWN = 0;lastKEYIN = KEYIN;BKtime = 0;}
        }
        if ((BKtime > 75) && (KEYIN == 1) && (MODE == 1) && (TXEN == 1)) {
            TXEN =0;BKtime = 0;

        }
		if (BKtime > 3000) {BKtime = 3000;}
		if (KEYIN == 0)  {
			CWtoneFlg = 1;
			TMR4ON = 1;
    		TMR4IE = 1;
		} else {CWtoneFlg = 0;}
        LED = ~LED;
   	}
 }
	
