/***********************************************************************/
/* */
/* FILE :sh_zenka_hilbert.c */
/* DATE :Tue, Feb 03, 2004 */
/* DESCRIPTION :Main Program */
/* CPU TYPE :SH7047 */
/* */
/* This file is generated by Renesas Project Generator (Ver.3.0). */
/* */
/***********************************************************************/
#include "start.h"

#define N 81
#define K 15

short fir[N]={
// 次数=80 タップ数=81 Q15
// サンプリング= 26.93KHz
// 帯域端周波数 = 0.3 KHz - 13.165KHz


-260,-403,101,-255,11,-251,-11,-287,-16,-336,
-17,-394,-17,-462,-17,-539,-16,-629,-16,-734,
-15,-859,-14,-1010,-13,-1196,-12,-1434,-10,-1750,
-9,-2197,-7,-2885,-5,-4104,-4,-6913,-2,-20847,
0,20847,2,6913,4,4104,5,2885,7,2197,
9,1750,10,1434,12,1196,13,1010,14,859,
15,734,16,629,16,539,17,462,17,394,
17,336,16,287,11,251,-11,255,-101,403,
260
};

short fir2[K]={
// 次数=14 タップ数=15 Q15
// サンプリング= 26.93KHz
// 帯域端周波数 = 1 KHz - 13.93KHz


-2811,1,-3323,1,-6417,0,-20677,0,20677,0,
6417,-1,3323,-1,2811

};

short data_up[N]={0};
short data_low[N]={0};

short sin_up[K]={0};
short sin_low[K]={0};

short data=0;
short out=0;
short moto_data=0;
short real_y=0;
short imag_y=0;

int output=0;
int data_chukan=0;

inline void kakunou(unsigned char j,short data3,unsigned char k)
{
    data_up[k-1-j]=data3; //下から格納する
    data_low[k-1-j]=data3; //同じ
}

inline void sin_kakunou(unsigned char j,short data3,unsigned char k)
{
    sin_up[k-1-j]=data3;
    sin_low[k-1-j]=data3;
}


inline int macw( short *a,short *b )
{
    int c;
    asm("clrmac");
    asm("mov.l %0,r2\n"
    "mov.l %1,r3"::"m" (a),"m" (b) );
    asm(".rept 81 \n" //ここのNだけは、手動で変える事
    "mac.w @r2+,@r3+\n"
    ".endr");
    asm("sts MACL,r4\n" //積和MACの下位だけr4に移す。
    "mov.l r4,%0":"=m" (c));
    return c; //int Cを返す
}
inline int macw2( short *a,short *b )
{
    int c;
    asm("clrmac");
    asm("mov.l %0,r2\n"
    "mov.l %1,r3"::"m" (a),"m" (b) );
    asm(".rept 15 \n" //ここのNだけは、手動で変える事
    "mac.w @r2+,@r3+\n"
    ".endr");
    asm("sts MACL,r4\n" //積和MACの下位だけr4に移す。
    "mov.l r4,%0":"=m" (c));
    return c; //int Cを返す
}
//************************************************************

int sinw=0 ; //Q15 a1=sinw 2KHz sampling 26.93Hz

int const1_cosd=0; //Q17 b0=1-cosd

//************************************************************

int main(void)
{

    InitSH();
    unsigned int i=0;
    unsigned int j=0;
    sinw=14742/120 ;
    const1_cosd=14013;
//initialize zenkashiki
    asm("mov.l %0,r9"::"m" (const1_cosd) ); //r9=1-cosd 2^17
    asm("mov.l %0,r10"::"m" (sinw) ); //r10=sinw
    asm("mov #0,r11" ); //r11=sin(w-deltaw)=0
    asm("mov.l r9, @-r15\n" //PUSH r9 [1-cosd]
    "mov.l r10, @-r15\n" //PUSH r10 [sinw]
    "mov.l r11, @-r15" ); //PUSH r11 [sin(w-d)]

    while(1)
    {

        if (AD0_READY)
        {

            data=getAD();
            data -=512;//無入力時のAD0の値


//AD変換の結果をhilbert変換器に通す---------------------------------------------------------------------
            kakunou(i,data,N);
            data_chukan=macw( (data_up+N-1-i),fir);

            data=data_chukan>>15;

            moto_data=data_up[N-1-i+(N-1)/2];//N-1-iから40ポイント前の点=中点
   
//sin波形の、漸化式による発生
//*****************************************************************
            asm("mov.l @r15+,r11"); //POP r11 [sin(w-d)]
            asm("mov.l @r15+,r10"); //POP r10 [sinw]
            asm("mov.l @r15+,r9"); //POP r9 [1-cosd]

            asm("mov r9,r1"); //r1=r9=1-cosd r9 保存される
            asm("mov r10,r0"); //r0=r10=sinw

            asm("muls r1,r0"); //(1-cosd)*sinw --to MACL 2^32
            asm("shll16 r0"); // r0=r0*2^16 sinw 2^31
            asm("shll r0"); // r0=r0*2 sinw 2^32

            asm("sts MACL,r1"); //積をr1に移す r1=(1-cosd)*sinw
                                         //r0=sinw(2^32)
            asm( "sub r1,r0"); //r0=sinw-(1-cosd)*sinw=cosd*sinw
            asm("shlr16 r0"); //上の結果をシフト 2^32--2^16=2^16 = 2*(cosd*sinw) 2^15
            asm("exts.w r0,r1"); //r1=r0この結果を、符号拡張してr1に保存
            asm("sub r11,r1"); //2cosd*sinw-sin(w-deltaw)

            asm("mov r10,r11"); //r11=new sin(w-deltaw)
            asm("mov r1,r10" ); //r10=new sinw
            asm("mov.l r9,@-r15"); //PUSH r9 [1-cos]
            asm("mov.l r10,@-r15"); //PUSH r10 [sinw]
            asm("mov.l r11, @-r15");//PUSH r11 [sin(w-d)]
            asm("mov.w r10,%0":"=m" (out) );

            sin_kakunou(j,out,K); //一旦、配列に格納する

//作成したsin波を、hilbert変換器に通し、虚部を求める

            data_chukan=macw2( (sin_up+K-1-j),fir2);

            imag_y=data_chukan>>15;
            real_y=sin_up[K-1-j+(K-1)/2];//K-1-iから、(K-1)/2 ポイント前の点=中点

            output=moto_data*real_y - data*imag_y;

            output=output>>8; //これは実測により決定する


            // output= (i%2) ? moto_data : data; //AD変換後の入力の、直交確認

            // output=(j%2) ? real_y : imag_y; //漸化式sinの直交確認

            output +=512;
            putDA(output);
            i++;
            j++;
            if( i==N) i=0;
            if( j==K) j=0;
         }

    }
return 1;
}