AVR SDR

My project on mega 644 ...

#include <math.h>

#include <util/delay.h>

#include <avr/io.h>

#include <avr/interrupt.h>

#define Ntap 31

#define DCgain 32768

#define ADC_VREF_TYPE ((1<<REFS1) | (1<<REFS0) | (0<<ADLAR)) // Внутренне опорное напряжение 2,56 Вольта

#define LED_PORT PORTC

#define Led_I 1

#define Led_Q 2

#define Led_Run 0



// Глобальные переменные

int OutSample,I,Q,N,X1,X2,X3,Y1,Y2,Y3;

float count=0;

int led_flag=0;

int cos_N[4]={1,0,-1,0};

int sin_N[4]={0,1,0,-1};

int sin_N_m[4]={0,-1,0,1};


// Читаем ADC

int read_adc(unsigned char adc_input)

{

ADMUX=adc_input | ADC_VREF_TYPE;

// Delay needed for the stabilization of the ADC input voltage

_delay_us(10);

// Start the AD conversion

ADCSRA|=(1<<ADSC);

// Wait for the AD conversion to complete

while ((ADCSRA & (1<<ADIF))==0);

ADCSRA|=(1<<ADIF);

return ADCW-512; // Убираем постоянную составляющую (преобразуем однополярный сигнал в двухполярный)

}




// Инициализация ADC

void adc_init(void)

{

DIDR0=(0<<ADC7D) | (0<<ADC6D) | (0<<ADC5D) | (0<<ADC4D) | (0<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (0<<ADC0D);

ADMUX=ADC_VREF_TYPE;

ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);

ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);

}


// Настройка генератора

void clk_init(void)

{

CLKPR=(1<<CLKPCE);

CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);

}

// Инициализация портов


void port_init(void)

{

// Порт А на ввод ADC (подтягивающие резисторы не включены)

PORTA=0x00;

DDRA=0x00;

// Порт С на вывод

PORTC=0x00;

DDRC=0xFF;

// Порт D на вывод

PORTD=0x00;

DDRD=0xFF;

}


// Настройки таймера 1 (Срабатывание по совпадению)

void timer_init(void)


{


// Timer/Counter 1 initialization

// Clock source: System Clock

// Clock value: 312,500 kHz

// Mode: Normal top=0xFFFF

// OC1A output: Disconnected

// OC1B output: Disconnected

// Noise Canceler: Off

// Input Capture on Falling Edge

// Timer Period: 0,20972 s

// Timer1 Overflow Interrupt: Off

// Input Capture Interrupt: Off

// Compare A Match Interrupt: On

// Compare B Match Interrupt: Off

TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);

TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (1<<CS10);

TCNT1H=0x00;

TCNT1L=0x00;

ICR1H=0x00;

ICR1L=0x00;

OCR1AH=0x01;

OCR1AL=0x77;

OCR1BH=0x00;

OCR1BL=0x00;

// Включение прерываний по таймеру

TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (1<<OCIE1A) | (0<<TOIE1);

}




// Фильтр канала I

int fir_I(int NewSample) {

int FIRCoef[Ntap] = {

-406,

-207,

529,

240,

-698,

-274,

942,

308,

-1317,

-338,

1972,

363,

-3441,

-379,

10572,

17042,

10572,

-379,

-3441,

363,

1972,

-338,

-1317,

308,

942,

-274,

-698,

240,

529,

-207,

-406

};


static int x[Ntap]; //input samples

long int y=0; //output sample

int n;


//shift the old samples

for(n=Ntap-1; n>0; n--)

x[n] = x[n-1];


//Calculate the new output

x[0] = NewSample;

for(n=0; n<Ntap; n++)

y += FIRCoef[n] * x[n];

return y / DCgain;

}




// Фильтр канала Q

int fir_Q(int NewSample) {

int FIRCoef[Ntap] = {

-406,

-207,

529,

240,

-698,

-274,

942,

308,

-1317,

-338,

1972,

363,

-3441,

-379,

10572,

17042,

10572,

-379,

-3441,

363,

1972,

-338,

-1317,

308,

942,

-274,

-698,

240,

529,

-207,

-406

};


static int x[Ntap]; //input samples

long int y=0; //output sample

int n;


//shift the old samples

for(n=Ntap-1; n>0; n--)

x[n] = x[n-1];


//Calculate the new output

x[0] = NewSample;

for(n=0; n<Ntap; n++)

y += FIRCoef[n] * x[n];

return y / DCgain;

}



// Обработчик прерывания по таймеру 1200 Гц

ISR (TIMER1_COMPA_vect)


{


if (N==3)

{

N=0;

}

else N++;

I=read_adc(0);

Q=read_adc(1);

X1=I*cos_N[N]+Q*sin_N[N];

X2=fir_I(X1);

X3=X2*cos_N[N];

Y1=I*sin_N_m[N]+Q*cos_N[N];

Y2=fir_Q(Y1);

Y3=Y2*sin_N_m[N];

OutSample=X3+Y3;

PORTD=OutSample+512;// восстанавливаем однополярный сигнал


}




int main (void)

{

//Инициализация ADC

adc_init();

//Инициализация генератора

clk_init();

// Инициализация портов

port_init();

// Инициализация таймера

timer_init();

// Разрешение прерываний

sei();

while(1)

{

// Led_Run индикатор просчета фильтров

if (count==1000)

{

led_flag=1;

}

else

{

count++;

}

if (led_flag==1)

{

LED_PORT |= 1 << Led_Run; //зажечь

led_flag=0;

count=0;

}

else

{

LED_PORT &= ~(1 << Led_I);// Гасим

}

if (I==0)

{

// Зажигаем диод I

LED_PORT |= 1 << Led_I; //зажечь

}

else

{

// Гасим диод I

LED_PORT &= ~(1 << Led_I);// Гасим

}

if (Q==0)

{

// Зажигаем диод Q

LED_PORT |= 1 << Led_Q; //зажечь

}

else

{

// Гасим диод Q

LED_PORT &= ~(1 << Led_I);// Гасим

}

}


}