/*
    SSB ジェネレーター   Ver 1.2.4
    2024年11月4日
	XC16 V1.50  dspic33F-GP-MC_DEFP 1.364
    XC16 CCI準拠 XC16-gcc option categories:Preprocessing 
    and messages の中にある Use CCI syntax にチェックマークを追加する事。
    XC16-gcc option　に    -ffixed-w8 -ffixed-w9 -ffixed-w10 -ffixed-w11 を追加する事
    クロック用 Xtal :24MHz
    クロック周波数 :fvco=160MHz Fosc=80MHz Fcy=40MHz ACLK=10MHz
    DACサンプリング周波数 :39.0625kHz  周期：25.6uS
    DSBサブキャリア 9766Hz
    USB/LSB選択対応、AGC用PWM出力対応  
    TX/RX共用対応
    MODE 00;LSB 01:USB 10:CW 11:AM
    CWKey i/o破損の為A4からB4へ変更
AGC出力 i/o破損の為RB5からRB2へ変更(v1.1)
 * Audio ｆ特低域改善 v1.2.0
 * AMのDAC出力を4倍→2倍　v1.2.1
 * CW,AMキャリアレベル調整 v1.2.4
 */

#define FCY 40000000UL                 // 80MHz / 2
#include <xc.h>                        //
#include <stdlib.h>
#include <libpic30.h>                  // 遅延ライブラリ

#include "float_TapAUDIOwide201_BPF_BL.h"
#include "float_TapLSB301_BPF_BL.h"
#include "float_TapUSBwide401_BPF_BL.h"
#include "float_TapAM301_BPF_BL.h"
#include "float_TapCW301_BPF_HM.h"
#include "float_Tap950_BPF.h"


#pragma config FNOSC = PRIPLL,FCKSM = CSDCMD,OSCIOFNC = OFF
#pragma config IESO = OFF,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 PORTBbits.RB4  //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領域にリングメモリ配列

//sinカーブ
signed int sin_coef[] = {0x0000, 0x7FFF, 0x0000, 0x8000};
unsigned int repeatPRE_Num, Tap_coef_pre_adr;
unsigned int repeatPOST_Num, Tap_coef_post_adr;
unsigned int X_RingMemory_adr;
unsigned int Y_RingMemory_adr;
unsigned int sin_coef_adr;
unsigned int sin_pointor;
unsigned int sin_pointor_adr;
unsigned int AMRX, AMTX, CWTX, CWRX, CWmark;
signed int AGCdata, AMC, CWC, Pdata;

unsigned int Xmod_start; //
unsigned int Xmod_end;
unsigned int Ymod_start; //
unsigned int Ymod_end;
unsigned char currMODE;
unsigned int UAGCdata, lastUAGCdata;
unsigned int TAP_PRE_Num;
unsigned int TAP_POST_Num;



//IF2のサイドバンドは反転しているので、システムが指定したUSB/LSB(currMODE)と
//以下のフィルターの中では逆サイドバンドになる。

void setTAP_MODE() {//BPFのTAP係数設定 
    unsigned int i = 0;

    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;
            ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
            Tap_coef_pre[i] = (signed int) ie;
        }


        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;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_post[i] = (signed int) ie;
            }
        }

        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);
                Tap_coef_post[i] = (signed int) ie;
            }
        }


        if (currMODE == 2) {//System= CW
            CWTX = 1;
            AMRX = 0;
            AMTX = 0;
            TAP_POST_Num = Tap10kAM_Num;
            for (i = 0; i < TAP_POST_Num; i++) {//   CW送信モード：post BPFを 10KAMへ
                ie = Tap10kAM_coef_float[i]*32767;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_post[i] = (signed int) ie;
            }
        }

        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;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_post[i] = (signed int) ie;
            }
        }

    } //TXモード選択終了

    //RXモードPRE BPF選択開始
    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を10KLSBへ
                ie = Tap10kLSB_coef_float[i]*32767;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_pre[i] = (signed int) ie;
            }
        }


        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を 10KUSBへ
                ie = Tap10kUSB_coef_float[i]*32767;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_pre[i] = (signed int) ie;
            }
        }

        if (currMODE == 2) {//System=RX & CW
            CWTX = 0;
            AMRX = 0;
            AMTX = 0;
            TAP_PRE_Num = Tap10kCW_Num;
            for (i = 0; i < TAP_PRE_Num; i++) {//   CW受信モード：pre BPFを 10KCWへ
                ie = Tap10kCW_coef_float[i]*32767;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_pre[i] = (signed int) ie;
            }
        }
        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;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_pre[i] = (signed int) ie;
            }
        }
    }

    //受信時のPOST BPFの選択
    if (TXMsw == 0) {
        if (currMODE == 3) {
            AMRX = 1;
        } else {
            AMRX = 0;
        }
        if (currMODE == 2) {// CW受信モードのみ
            CWTX = 0;
            AMRX = 0;
            AMTX = 0;
            CWRX = 1;
            TAP_POST_Num = Tap950_Num;
            for (i = 0; i < TAP_POST_Num; i++) {//            受信モード：Post BPFを950HzBPFへ
                ie = Tap950_coef_float[i]*32767;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_post[i] = (signed int) ie;
            }

        } else { //CW以外の全モード受信
            CWTX = 0;
            AMTX = 0;
            CWRX = 0;
            TAP_POST_Num = Tap3k_Num;
            for (i = 0; i < TAP_POST_Num; i++) {//            受信モード：Post BPFを3KHzBPFへ
                ie = Tap3k_coef_float[i]*32767;
                ie = (ie >= 0.0) ? (ie + 0.5) : (ie - 0.5);
                Tap_coef_post[i] = (signed int) ie;
            }

        }

    }

}




//  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 = 0b0000000000000001; //RA0:in(AN0) 
    LATA = 0x0000; //PORTA all L

    TRISB = 0b0000001100011100; //RB2,3,4,8,9 input other all out RB4:CWKey
    LATB = 0x0000; //PORTB all L
    RPOR1bits.RP2R = 18; //RP2(RB2)に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;
        DAC1STATbits.LOEN = 0;
    } else {
        DAC1STATbits.LOEN = 1;
        DAC1STATbits.ROEN = 0;
    }
    //AGC用PWM出力設定
    T2CON = 0x0000; //T2 16bit 1/1プリスケーラ
    OC1CON = 0x0006; //OC1 PWMモード  比較レジスタ:TMR2

    PR2 = 1023;
    OC1RS = 0;
    OC1R = 1023;

    T2CONbits.TON = 1; //T2スタート

    //Timer3によるサンプリング周期設定
    T3CONbits.TCKPS = 0;
    PR3 = 1023; //40MHz/1024の周波数で割り込み
    TMR3 = 0;
    IFS0bits.T3IF = 0;
    IPC2bits.T3IP = 4;
    __delay_us(30); //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");

//    asm("mov W0, _AGCdata"); //AGC用出力
    asm("btsc _CWTX,#0");
    asm("goto LABL2"); //_CWTXならLABL2へ

    //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用出力

    /*
_AMRX AM受信時のみ１  他は0
_AMTX AM送信時のみ1  他は0   _AMC AMのキャリアレベル
_CWTX CW送信時のみ1  他は0	_CWC CWのキャリアレベル
_CWkey CWキーダウン（マーク）時のみ1  スペース時0
     */


    asm("btsc _AMRX,#0");
    asm("goto LABL1"); //_AMRX=1ならLABL1へ

    asm("btsc _AMTX,#0");
    asm("goto LABL3"); //_AMTX=1ならLABL3へ
    asm("goto LABL4");

    asm("LABL1:"); //AMRX start
    asm("nop");
    asm("add #0,W0");
    asm("bra NN,LABL6"); //Mixerをskip
    asm("clr W0");
    asm("nop");
    asm("goto LABL6"); //Mixerをskip AMRX end

    asm("LABL2:");
    asm("nop");    
    asm("clr W4");
    asm("btsc _CWmark,#0"); //CWkey=0ならスキップ
    asm("mov _CWC,W4"); //CWキャリアレベル設定
    asm("nop");
    asm("goto LABL4");

    asm("LABL3:");
    asm("mov W4,W0");
    asm("asr W0,#2,W2"); //右シフト2回 W0を1/4してW2に保持
    asm("mov _AMC,W0");
    asm("add W0,W2,W4"); //AMキャリアレベル + 音声信号





    asm("LABL4:");//MODE選択処理終了

    //サブキャリアによるミキシング  サブキャリア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");//アキュムレータAをクリアーしてW9が示すアドレスのデータをW5にコピー
    asm("mpy W4 * W5,A"); //w4とw5の積をアキュムレータAにセット
    asm("sac A,W0"); //結果をラウンド処理してw0にコピー

    asm("LABL6:");

    //FIR POST BPF処理

    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("sl W0,#1,W1"); //レベル補正　2倍にする
    asm("btsc _AMRX,#0");
    asm("sl W0,#1,W1"); //_AMRX=1ならレベル補正2倍にする

//    asm("mov W1, _Pdata"); //POWER用出力    
//    asm("nop");


    //DAC処理
    asm("mov W1,DAC1RDAT"); //RX出力
    asm("mov W1,DAC1LDAT"); //TX出力


    //	T1CON = 0x0000;;//テスト用 T1stop 結果はTMR1

}
 
int main(void) {

    initmain();
    T3IEoff;
    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 = 2250; //AMキャリアレベル
    CWC = 4150; //CWキャリアレベル



    UAGCdata = 0;
    if (MODE0 == 1) {
        LED0 = 1;
    } else {
        LED0 = 0;
    }
    if (MODE1 == 1) {
        LED1 = 1;
    } else {
        LED1 = 0;
    }
    T3on;
    T3IEon;

    while (1) {

        CWmark = CWkey; //CWキーイング
        if (TXMsw == 1) {
        	UAGCdata = 0;//abs(Pdata) >>8; 
//        	if (UAGCdata > 240) {UAGCdata = 240;}
        } else {//post BPF通過後のレベル
            UAGCdata = abs(AGCdata) >> 6;
        }//pre BPF通過後のレベル

        OC1RS = UAGCdata; //RB5にAGC用PWM出力　弱入力で0V、FET　G2用は反転する事
     
    }
}




