Demo: IIR filter with o-scope output
Reinhard
Posts: 489
/* Demonstrate an IIR Filter (Highpass) with fixed point arithmetic in pure C Signal out on P0 via RC Lowpass ; R = 470 Ohm C = 1µF Can observed with osci ( 0.5 V/Div 10ms/Div ) shows alternate the input test signal and the filtered output on 1 osci channel Testinput Signal is generated per programm (Square puls) IIR Highpass 1. Order y[0] = A[0] * x[0] + A[1] * x[1] - B[1] * y[1]; out = B[0] * y[0]; compile : propeller-elf-gcc -mlmm -Os -o IIR.elf main.c -------------------------------------------------------------------------- */ #include <stdio.h> #include <stdlib.h> #include <propeller.h> #include "fixed.h" #define N 100 #define q 14 #define STACKSIZE 20 static int samples[N]; // the test input signal int PWM; static int cog_stack[STACKSIZE]; void Task_PWM_Pin0 (); void start_lmm(void *func, int *stack_top); void msleep(int t); void input(); void filter (); /////////////////////////////////////////////////////////////////////////// int main() { int n; // common used index for(n=0;n<N;n++) // Setup the test signal samples[n] = TOFIX(0.0,q); for(n=N/4;n<=N/2;n++) samples[n] = TOFIX(1.0,q); start_lmm(Task_PWM_Pin0, cog_stack + STACKSIZE); while(1) { input(); // show the input signal on osci msleep(10); filter(); // show the filtered signal on osci msleep(10); } return 0; } /////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void Task_PWM_Pin0 () { int t; int tInc = CLKFREQ/1000000; int tC = 100 * tInc; CTRA = (1<<28) + 0; FRQA = 1; DIRA |= (1 << 0); t = CNT; while(1) { PHSA = - PWM * tInc; t += tC; waitcnt(t); } } /////////////////////////////////////////////////////////////////////////// void start_lmm(void *func, int *stack_top) { extern unsigned int _load_start_kernel[]; /* push the code address onto the stack */ --stack_top; *stack_top = (int)func; /* now start the kernel */ cognew(_load_start_kernel, stack_top); } /////////////////////////////////////////////////////////////////////////// void msleep(int t) { waitcnt((CLKFREQ/1000)*t+CNT); } /////////////////////////////////////////////////////////////////////////// void input() { int n; for(n=0;n<N;n++) { PWM = 50 + (samples[n]/320); msleep(1); } } /////////////////////////////////////////////////////////////////////////// void filter () { int n; // common used index int T1,T2,T3,T4; // Help Terms int out; // the filter output int A[2]; // Forward Coefficients int B[2]; // Reverse Coefficients int x[2]; // Forward stage int y[2]; // Reverse stage A[0] = TOFIX(0.9695,q); // Setup Filter A[1] = TOFIX(-0.9695,q); // Set Coefficients B[0] = TOFIX(1.0,q); B[1] = TOFIX(-0.9391,q); x[0] = 0; x[1] = 0; y[0] = 0; y[1] = 0; for(n=0;n<N;n++) // Filter Loop { x[0] = samples[n]; T1 = FMUL(B[1],y[1],q); T2 = FMUL(A[1],x[1],q); T3 = FMUL(A[0],x[0],q); T4 = FADD(T3,T2); y[0] = FSUB(T4,T1); out = FMUL(B[0],y[0],q); x[1] = x[0]; y[1] = y[0]; PWM = 50 + (out/320); msleep(1); //printf("%d %f %f %d\n",n,TOFLT(samples[n],q),TOFLT(out,q),out); } } ///////////////////////////////////////////////////////////////////////////
Comments
A tip: you can replace your start_lmm function with _start_cog_thread, as documented in the Library.html file in the doc/ directory. It does pretty much the same thing as start_lmm, but also adds a parameter to the function you are starting, and a library state so that the new thread can use "errno", "gmtime", and other C library features that require internal storage. Or you can use pthreads, which are even higher level and also work in XMM mode (though there they have to run on the same cog).
Eric
I'll do it.
The things to do with the combination propeller and propgcc with small effort are simple infinit.
(If I had an infinit amount of time :-)
Reinhard