//ADC to PWM #include #include // //I like these definitions #define begin { #define end } #define int2fix(a) (((int)(a))<<8) //Convert char to fix. a is a char #define float2fix(a) ((int)((a)*256.0)) #define fix2int(a) ((signed char)((a)>>8)) //Convert fix to char. a is an int #define countNum 4000 // slow down sample rate //IIR stuff #pragma regalloc- int alpha, yn_1 ; #pragma regalloc+ char newReady ; //ISR communication flag unsigned int count ; //state variable to slow down sampling //======================================================== int OnePoleLow(int xx) // xx is the current input signal sample // returns the current filtered output sample begin #asm .macro mult_acc ;r31:r30:r24 += r23:r22 * r21:r20 muls r23, r21 ; (signed)ah * (signed)bh add r31, r0 mul r22, r20 ; al * bl add r24, r0 adc r30, r1 adc r31, r27 mulsu r23, r20 ; (signed)ah * bl add r30, r0 adc r31, r1 mulsu r21, r22 ; (signed)bh * al add r30, r0 adc r31, r1 .endm push r20 ;save parameter regs push r21 clr r27 ;permanent zero clr r24 ;clear 24 bit result reg; msb to lsb => r31:r30:r24 ld R30, Y ;load input parameter xx from stack ldd R31, Y+1 ; and put in result location lds R20, _yn_1 ;load y(n-1) from RAM lds R21, _yn_1+1 sub r20, r30 ;form y(n-1) - xx sbc r21, r31 lds R22, _alpha ;load alpha from RAM lds R23, _alpha+1 mult_acc ; alpha*(yn_1 - xx)) + xx sts _yn_1, r30 ;store new output as y(n-1) to RAM sts _yn_1+1, r31 pop r21 ;restore parameter regs pop r20 #endasm end //================================================================= interrupt [TIM0_OVF] void sgen(void) begin count--; if (count==0) begin count = countNum ; //read ADC, lowpass, send to PWM OCR0 = fix2int(OnePoleLow(int2fix(ADCH))) ; //start another conversion ADCSR.6=1; newReady = 1; end end //================================================================= void main(void) begin //PORTB has PWM out DDRB=0xff; //PORTA is analog input DDRA = 0b0 ; //all analog inputs with pullup off. PORTA = 0b0; //turn on pwm with period= 256*8 cycles = 2048 cycles // or 7812 samples/sec //fast PWM mode, TCNT0 = 0; OCR0 = 128; TCCR0 = 0b01101010 ; //turn on timer 0 overflow ISR TIMSK = 0b00000001 ; //init the A to D converter //channel zero/ left adj /EXTERNAL Aref //!!!CONNECT Aref jumper!!!! ADMUX = 0b00100000; //enable ADC and set prescaler to 1/128*16MHz=125,000 //and clear interupt enable //and start a conversion ADCSR = 0b11000111; //init the UART UCSRB = 0x18; UBRRL = 103; printf("starting...\n\r"); #asm sei #endasm //set IIR filter alpha = float2fix(0.875) ; //set sample rate count = countNum ; while(1) begin if (newReady==1) begin newReady=0; printf("%f\n\r", (float)OCR0/256.0*5.0) ; end end // end while end //end main