/*
	SSB ジェネレーター   Ver 0.83
	2020年7月25日
	
	XC16 CCI準拠 XC16(Global Option) option categories:Preprocessing 
	and messages の中にある Use CCI syntax にチェックマークを追加する事。
	XC16-GCCのoptions:に -menable-fixed の文字を追加する事
	
    クロック用 Xtal :24MHz
    クロック周波数 :fvco=160MHz Fosc=80MHz Fcy=40MHz ACLK=10MHz
    DACサンプリング周波数 :39.0625kHz  周期：25.6uS
    DSBサブキャリア 9766Hz
    USB/LSB選択対応、AGC用PWM出力対応  
    TX/RX共用対応(pre BPFとpost BPFのTAP数は同じである事。
    MODE 00;LSB 01:USB 10:CW 11:AM 但し、まだCWの実装なし AMはBPFのみ
*/

#define FCY 40000000UL                 // 80MHz / 2
#include <xc.h>                        //
#include <stdlib.h>
#include <libpic30.h>                  // 遅延ライブラリ

#include "float_Tap2800_BPF.h"
#include "float_Tap10kLSB_BPF.h"
#include "float_Tap10kUSB_BPF.h"
#include "float_Tap10kAM_BPF.h"
//#include "float_Tap10kCW_BPF.h"
//#include "float_Tap700_BPF.h"

#pragma config FNOSC = PRIPLL,FCKSM = CSECMD,OSCIOFNC = OFF
#pragma config IESO = ON,GSS = OFF,GWRP = OFF
#pragma config POSCMD = HS,FWDTEN = OFF

#define LED0 LATBbits.LATB6
#define LED1 LATBbits.LATB7

#define TXMsw PORTBbits.RB3  //TXM/RXM input
#define T3IEon IEC0bits.T3IE=1;
#define T3IEoff IEC0bits.T3IE=0;
#define T3on T3CONbits.TON=1
#define T3off T3CONbits.TON=0
#define MODE0 PORTBbits.RB8  //MODE0 input
#define MODE1 PORTBbits.RB9  //MODE1 input
#define CWkey PORTAbits.RA4  //CWkey Mark input

__ydata  signed int Tap_coef_pre[1024] ; // Y領域にPRE TAP係数を配列
__xdata signed int X_RingMemory[1024];// X領域にリングメモリ配列
__xdata  signed int Tap_coef_post[1024] ; // X領域にPOST TAP係数を配列
__ydata signed int Y_RingMemory[1024];// Y領域にリングメモリ配列



unsigned int Tap_coef_pre_adr;
unsigned int Tap_coef_post_adr;
unsigned int X_RingMemory_adr;
unsigned int Y_RingMemory_adr;
unsigned int repeatPRE_Num,TAP_PRE_Num;
unsigned int repeatPOST_Num,TAP_POST_Num;
unsigned int Xmod_start; //
unsigned int Xmod_end;
unsigned int Ymod_start; //
unsigned int Ymod_end; 
unsigned int sin_coef_adr;
unsigned int sin_pointor;
unsigned int sin_pointor_adr; 
unsigned int UAGCdata,AMRX,AMTX,CWTX,CWmark; 
signed int AGCdata,AMC,CWC;
unsigned char currMODE;
//sinカーブ
signed int sin_coef[]={0x0000,0x7FFF,0x0000,0x8000};



//IF2のサイドバンドは反転しているので、システムが指定したUSB/LSB(currMODE)と
//以下のフィルターの中では逆サイドバンドになる。
void setTAP_MODE(){//BPFのTAP係数設定 
	unsigned int i=0;
    signed int id;
    float ie;
	if (TXMsw == 1) {//TXモード選択開始
		TAP_PRE_Num = Tap3k_Num;
		 for (i=0;i<TAP_PRE_Num;i++) {//           送信モード：Pre BPFを3KHzBPFへ
        	ie=Tap3k_coef_float[i]*32767;
            __delay_us(1);
        	ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        	id=(signed int)ie;
           	__delay_us(1);
          	Tap_coef_pre[i]=id;
    	}
	
	
	if (currMODE == 0) {//System=LSB
		CWTX = 0;AMRX = 0;AMTX = 0;
		TAP_POST_Num = Tap10kU_Num;
		 for (i=0;i<TAP_POST_Num;i++) {//  LSB送信モード：post BPFを10KUSB へ
            ie=Tap10kUSB_coef_float[i]*32767;
            __delay_us(1);
         	ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        	id=(signed int)ie;
           	__delay_us(1);
         	Tap_coef_post[i]=id;
	   	}
        asm("nop");
	} 
	
	if  (currMODE == 1) {//System=USB
		CWTX = 0;AMRX = 0;AMTX = 0;
		TAP_POST_Num = Tap10kL_Num;
		 for (i=0;i<TAP_POST_Num;i++) {//   USB送信モード：post BPFを 10KLSBへ
            ie=Tap10kLSB_coef_float[i]*32767;
         	ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        	id=(signed int)ie;
           	__delay_us(1);
         	Tap_coef_post[i]=id;
            }
        }
        
                
	if  (currMODE == 2) {//System= CW
		CWTX = 1;AMRX = 0;AMTX = 0;
		TAP_POST_Num = Tap10kAM_Num;
		for (i=0;i<TAP_POST_Num;i++) {//   AM送信モード：post BPFを 10KAMへ
            ie=Tap10kAM_coef_float[i]*32767;
            __delay_us(1);           
         	ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        	id=(signed int)ie;
           	__delay_us(1);
         	Tap_coef_post[i]=id;
            }
        }   
	
	if  (currMODE == 3) {//System= AM
		CWTX = 0;AMRX = 0;AMTX = 1;
		TAP_POST_Num = Tap10kAM_Num;
		for (i=0;i<TAP_POST_Num;i++) {//   AM送信モード：post BPFを 10KAMへ
            ie=Tap10kAM_coef_float[i]*32767;
            __delay_us(1);
         	ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        	id=(signed int)ie;
           	__delay_us(1);
         	Tap_coef_post[i]=id;
            }
        }   
		
	} //TXモード選択終了
	
	//RXモード選択開始
	if (TXMsw == 0) {
		if (currMODE == 1) {//System=RX & USB
			CWTX = 0;AMRX = 0;AMTX = 0;
			TAP_PRE_Num = Tap10kL_Num;
		 	for (i=0;i<TAP_PRE_Num;i++) {//   LSB受信モード：pre BPFを10KUSBへ
	   			ie=Tap10kLSB_coef_float[i]*32767;
                __delay_us(1);
        		ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        		id=(signed int)ie;
		 		__delay_us(1);
            	Tap_coef_pre[i]=id;
		 	}
		}
	
	
		if (currMODE == 0) {//System=RX & LSB
			CWTX = 0;AMRX = 0;AMTX = 0;
			TAP_PRE_Num = Tap10kU_Num;
		 	for (i=0;i<TAP_PRE_Num;i++) {//   USB受信モード：pre BPFを 10KLSBへ
	   			ie=Tap10kUSB_coef_float[i]*32767;
                __delay_us(1);
        		ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        		id=(signed int)ie;
		 		__delay_us(1);
           	Tap_coef_pre[i]=id;
		 	}
		}
	/*
		if (currMODE == 2) {//System=RX & CW
			CWTX = 1;AMRX = 0;AMTX = 0;
			TAP_PRE_Num = Tap10kCW_Num;
		 	for (i=0;i<TAP_PRE_Num;i++) {//   AM受信モード：pre BPFを 10KLSBへ
	   			ie=Tap10kCW_coef_float[i]*32767;
               __delay_us(1);
        		ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        		id=(signed int)ie;
		 		__delay_us(1);
            	Tap_coef_pre[i]=id;
		 	}
		}
		if (currMODE == 3) {//System=RX & AM
			CWTX = 0;AMRX = 1;AMTX = 0;
			TAP_PRE_Num = Tap10kAM_Num;
		 	for (i=0;i<TAP_PRE_Num;i++) {//   AM受信モード：pre BPFを 10KLSBへ
	   			ie=Tap10kAM_coef_float[i]*32767;
               __delay_us(1);
        		ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        		id=(signed int)ie;
		 		__delay_us(1);
            	Tap_coef_pre[i]=id;
		 	}
		}
     */
	}
	if (TXMsw ==0 ) {
        /*
		if (currMODE == 2) {
			TAP_POST_Num = Tap700_Num;
		for (i=0;i<TAP_POST_Num;i++) {//            受信モード：Post BPFを700HzBPFへ
        	ie=Tap700_coef_float[i]*32767;
           __delay_us(1);
        	ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        	id=(signed int)ie;
            __delay_us(1);
          	Tap_coef_post[i]=id;}
		} else {
         */
		TAP_POST_Num = Tap3k_Num;
		for (i=0;i<TAP_POST_Num;i++) {//            受信モード：Post BPFを3KHzBPFへ
        	ie=Tap3k_coef_float[i]*32767;
            __delay_us(1);
        	ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
        	id=(signed int)ie;
            __delay_us(1);
          	Tap_coef_post[i]=id;}
//		}
    
	}

}




//  PLLに関連する設定 
void PLLset() {
    CLKDIVbits.PLLPRE=1;               // N1 = 3  24MHz/3=8MHz set値=N1-2
	PLLFBDbits.PLLDIV = 18;            // M = 20  8MHz*20=160MHz set値=M-2
    CLKDIVbits.PLLPOST=0;              // N2 = 2  160MHz/2=80MHz set値=N2-2
	ACLKCONbits.SELACLK=0;      //DAC用clockはfvcoより供給
	ACLKCONbits.APSTSCLR=3;     // ACLK = fvco divided by 1/16 = 10MHz
    __builtin_write_OSCCONH(0x03);     // ロックを解除して PRI PLL にクロック源を指定
    __builtin_write_OSCCONL(0x01);     // ロックを解除して クロック変更を開始
    while (OSCCONbits.COSC != 0b011);  // クロック変更の開始を確認
    while (OSCCONbits.LOCK!=1);        // PLLの安定（LOCK)を待つ
}



void XY_MODset() {

    XMODSRT = Xmod_start;//Xリングメモリの先頭アドレス指定 
    XMODEND = Xmod_end; //Xリングメモリ最後尾アドレス指定
    MODCONbits.BWM = 0b1111; // Bit-reversed addressing disabled
    MODCONbits.XWM = 0b1000; //  Xリングメモリ制御レジスタ指定(W8)
	MODCONbits.XMODEN = 1; // X リングメモリ有効
    asm("mov _Xmod_start,W8");      //Xリングメモリー 先頭アドレスからスタート

    YMODSRT = Ymod_start;//Yリングメモリの先頭アドレス指定 
    YMODEND = Ymod_end; //Yリングメモリ最後尾アドレス指定

    MODCONbits.YWM = 0b1011; //  Yリングメモリ制御レジスタ指定(W11)
	MODCONbits.YMODEN = 1; // Y リングメモリ有効
    asm("mov _Ymod_start,W11");      // Yリングメモリー先頭アドレスからスタート 
}  

void initmain() {
	PLLset(); //PLL & OSC setup

	TRISA=0b0000000000010001;//RA0,4 in(AN0) CWkey
	LATA=0x0000;//PORTA all L

	TRISB=0b0000001100001100;//RB2,3,8,9 input other all out
	LATB=0x0000;//PORTB all L
	RPOR2bits.RP5R = 18;//RP5にOC1(PWM)を割り当て

	//ADC設定 AN0 12bit
	AD1PCFGL=0xFFFE;//PCFG0=0 other=1
	AD1CON3=0x0101; //System clock base Sample time bit 1 TAD Conv. clock 2
	AD1CON1=0b0000011101000100; //0x0744; 12bit
	AD1CON1bits.ADON=1;
    
	//DAC設定　
	DAC1STAT=0x0404;//0b0000010000000100;// Left Right DAC off
	DAC1CON=0b0001000100000000; //0x1100; AMP on 符号付 DAC clock ACLK 1/1
    DAC1CONbits.DACEN=1;    //DAC1 on
	currMODE = PORTB >> 8;
	currMODE = currMODE & 0x03;//0:LSB 1:USB 2:CW 3:AM
  
    setTAP_MODE();

    if (TXMsw == 1) {DAC1STATbits.ROEN = 1;} else {DAC1STATbits.LOEN = 1;}
	//AGC用PWM出力設定
    T2CON = 0x0000;//T2 16bit 1/1プリスケーラ
	OC1CON = 0x0006; //OC1 PWMモード  比較レジスタ:TMR2
//	T2CONbits.TCKPS = 3; //T2クロック=40MHz/256 156.25KHz
    PR2=2047;
    OC1RS = 0;
    OC1R =2047;
//	TMR2 = 0;
	T2CONbits.TON = 1;//T2スタート

    //Timer3によるサンプリング周期設定
	T3CONbits.TCKPS=0; 
	PR3=1023; //40MHz/1024の周波数で割り込み
	TMR3=0; 
    IFS0bits.T3IF =0;
    IPC2bits.T3IP=4;
    __delay_us(10); //DACが256以上アイドルするまで待つ

//	Timer1設定（テスト用）
// 	T1CON = 0x0000;//T1 Fcy直結分周比1/1
//	TMR1 = 0x0000;//T1カウンタクリア
}


void __interrupt( no_auto_psv) _T3Interrupt(void){//CCI対応
//	TMR1 = 0x0000;//テスト用 TMR1クリアー
//	T1CON = 0x8000;//テスト用T1 start
//ADCデータ取得
    asm("bclr IFS0,#8");// T3IFクリアー
    asm("mov ADC1BUF0,W0");// ADCのデータをW0にコピー
    asm("nop");

//FIR PRE BPF処理
    asm("mov _repeatPRE_Num,W3"); //リピート回数をW3にセット
	asm("mov _Tap_coef_pre_adr,W10");//TAP係数格納の先頭番地をW10に格納
    asm("mov W0,[W8++]");//Xリングメモリー 先頭アドレスからスタート       
    asm("clr A, [W8]+=2,W4,[W10]+=2,W5");
    asm("repeat W3");
	asm("mac W4 * W5, A, [W8]+=2, W4,[W10]+=2,W5");
    asm("mac W4 * W5,A");
    asm("sac A,W0");
	asm("mov W0,W4");

   	asm("mov W0, _AGCdata"); //AGC用出力


 	asm("nop");
//サブキャリアによるミキシング  サブキャリア39.0625KHz/4=9.766KHz
	asm("mov _sin_pointor,W1");//sinポインタをW1にセット
    asm("inc2 W1,W2");//W1+2をW2にセット
	asm("mov #0x0007,W1");//w1にANDのデータをセット
	asm("and W1,W2,W3");//w1とW2をANDした結果をW3にセット
    asm("mov W3,_sin_pointor");//W3をsin_pointorにセーブ
    asm("nop");
	asm("mov _sin_coef_adr,W1");//sin_coefアドレスをw1にセット
	asm("add W3,W1,W9");//W3とW1の加算結果をw9にセット
	asm("clr A,[W9],W5");
	asm("mpy W4 * W5,A");//w4とw5の積をアキュムレータAにセット
	asm("sac A,W0");//結果をラウンド処理してw0にコピ
	asm("LABL5:");

//FIR POST BPF処理
    asm("nop");
    asm("mov _repeatPOST_Num,W3"); //リピート回数をW3にセット
	asm("mov _Tap_coef_post_adr,W9");//TAP係数格納の先頭番地をW9に格納
    asm("mov W0,[W11++]");//Yリングメモリー 先頭アドレスからスタート
    asm("clr A, [W9]+=2,W4,[W11]+=2,W5");
    asm("repeat W3");
	asm("mac W4 * W5, A, [W9]+=2, W4,[W11]+=2,W5");
    asm("mac W4 * W5,A");
    asm("sac A,W0");
 //   asm("nop");
    asm("sl W0,#1,W1");//レベル補正　2倍にする
//DAC処理
  	asm("mov W1,DAC1RDAT");   //R出力
    asm("mov W1,DAC1LDAT");   //L出力
// 	asm("nop");

//	T1CON = 0x0000;;//テスト用 T1stop 結果はTMR1

}



int main (void){
    initmain();
	Tap_coef_pre_adr = (unsigned int)&Tap_coef_pre;
	Tap_coef_post_adr = (unsigned int)&Tap_coef_post;
    repeatPRE_Num = TAP_PRE_Num - 2;
	repeatPOST_Num = TAP_POST_Num - 2;
 	Xmod_start = (unsigned int)&X_RingMemory; //Ring Memory開始アドレス
 	Xmod_end = Xmod_start + (TAP_PRE_Num * 2) - 1;
	Ymod_start = (unsigned int)&Y_RingMemory; //Ring Memory開始アドレス
 	Ymod_end = Ymod_start + (TAP_POST_Num * 2) - 1;
    XY_MODset();
	sin_coef_adr = (unsigned int)&sin_coef;
	sin_pointor_adr = (unsigned int)&sin_pointor;
	sin_pointor = 0;
    CWmark = CWkey;
    AMC = 0x4000;//AMキャリアレベル
	CWC = 0x7FFF;//CWキャリアレベル

	UAGCdata = 0;
    
    T3on;
    T3IEon;
    if (MODE0 == 1) {LED0 =1;}else{LED0 = 0;}
    if (MODE1 == 1) {LED1 =1;}else{LED1 = 0;}
	while(1){
        
        CWmark = CWkey;
		UAGCdata = abs(AGCdata >> 1);//pre BPF通過後のレベルの絶対値

        OC1RS = UAGCdata;//RB5にAGC用PWM出力　弱入力で0V、FET　G2用は反転する事
       
 

	}
}




