SSB demodulator

ssb demodulator

#include <mega644.h>

#include <delay.h>

// Declare your global variables here

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

int cos_N[3]{1,0,-1,0}

int sin_N[3]{0,1,0,-1}

int sin_N_m[3]{0,-1,0,1}

// Voltage Reference: AREF pin

#define ADC_VREF_TYPE ((0<<REFS1) | (0<<REFS0) | (0<<ADLAR))

// Read the AD conversion result

unsigned 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;

}

#define Ntap 31

#define DCgain 32768

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;

}

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;

}

// Обработчик прерывания по совпадению таймера 1 (1200 Гц)

interrupt [TIM1_COMPA] void timer1_compa_isr(void)

{

I=read_adc(0);

Q=read_adc(1);

X1=I*cos_N+Q*sin_N

X2=fir_I(X1);

X3=X2*cos_N;

Y1=I*sin_N_m+Q*cos_N;

Y2=fir_Q(Y1);

Y3=Y2*sin_N_m;

OutSample=X3+Y3;

}

void main(void)

{

// Declare your local variables here

// Crystal Oscillator division factor: 1

#pragma optsize-

CLKPR=(1<<CLKPCE);

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

#ifdef _OPTIMIZE_SIZE_

#pragma optsize+

#endif

// Input/Output Ports initialization

// Port A initialization

// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);

// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization

// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);

// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization

// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);

// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization

// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In

DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);

// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T

PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// 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;

// Timer/Counter 2 initialization

// Clock source: System Clock

// Clock value: Timer2 Stopped

// Mode: Normal top=0xFF

// OC2A output: Disconnected

// OC2B output: Disconnected

ASSR=(0<<EXCLK) | (0<<AS2);

TCCR2A=(0<<COM2A1) | (0<<COM2A0) | (0<<COM2B1) | (0<<COM2B0) | (0<<WGM21) | (0<<WGM20);

TCCR2B=(0<<WGM22) | (0<<CS22) | (0<<CS21) | (0<<CS20);

TCNT2=0x00;

OCR2A=0x00;

OCR2B=0x00;

// Timer/Counter 1 Interrupt(s) initialization

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

// ADC initialization

// ADC Clock frequency: 625,000 kHz

// ADC Voltage Reference: AREF pin

// ADC Auto Trigger Source: ADC Stopped

// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On

// ADC4: On, ADC5: On, ADC6: On, ADC7: On

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);

#asm("sei")

while (1)

{

// Place your code here

}

}