// Chapter 15 6812 C programs // Jonathan W. Valvano, 2/26/07 // This software accompanies the book, // Embedded Microcomputer Systems: Real Time Interfacing, Second Edition // published by Thomson Engineering, 2006 // 9S12C32 C implementation, interrupts at a frequency of fs unsigned short x[2],y; // x[0] is x(n) current sample // x[1] is x(n-1) previous sample void interrupt 13 TC5handler(void){ TFLG1 = 0x20; // ack OC5F TC5 = TC5+PERIOD; // Executed every 1/fs x[1] = x[0]; // shift MACQ data x[0] = ADC_In(CHANNEL); // new data y = (x[0]+x[1])>>1; } void DAS_Init(void){ // start sampling asm sei // make atomic ADC_Init(); // Program 11.13 TIOS |= 0x20; // enable OC5 TSCR1 = 0x80; // enable, 4 MHz TCNT TIE |= 0x20; // Arm output compare 5 TFLG1 = 0x20; // Initially clear C5F TC3 = TCNT+50; // First one right away x[0] = x[1] = 0; asm cli } //Program 15.1. Real time data acquisition with a simple digital filter, Equation 2. // 9S12C32 C implementation, interrupts at 360Hz unsigned short n,x[12],y; // x[n] is x(n) current sample // x[n-1] is x(n-1) sample 1/360 sec ago // x[n-2] is x(n-2) sample 2/360 sec ago // x[n-3] is x(n-3) sample 3/360 sec ago // x[n-4] is x(n-4) sample 4/360 sec ago // x[n-5] is x(n-5) sample 5/360 sec ago void interrupt 13 TC5handler(void){ TFLG1 = 0x20; // ack OC5F TC5 = TC5+11111; // Executed at 360 Hz n++; if(n==12) n=6; x[n] = x[n-6] = ADC_In(CHANNEL); // new data y = (x[n]+x[n-1]+x[n-2]+x[n-3]+x[n-4]+x[n-5])/6; } void DAS_Init(void){ // start sampling asm sei // make atomic ADC_Init(); // Program 11.13 n = 6; // rotates through 6,7,8,9,10,11 TIOS |= 0x20; // enable OC5 TSCR1 = 0x80; // enable, 4 MHz TCNT TIE |= 0x20; // Arm output compare 5 TFLG1 = 0x20; // Initially clear C5F TC3 = TCNT+50; // First one right away asm cli } //Program 15.2. Real time data acquisition with a simple digital filter, Equation 3. // 9S12C32 C implementation, interrupts at 360Hz unsigned char x[4],y; // 8-bit ADC // x[0] is x(n) current sample // x[1] is x(n-1) sample 1/360 sec ago // x[2] is x(n-2) sample 2/360 sec ago // x[3] is x(n-3) sample 3/360 sec ago void interrupt 13 TC5handler(void){ TFLG1 = 0x20; // ack OC5F TC5 = TC5+11111; // Executed at 360 Hz x[3] = x[2]; // shift MACQ data x[2] = x[1]; x[1] = x[0]; x[0] = ADC_In(CHANNEL); // new 8-bit data y = (x[0]+x[3])>>1; } void DAS_Init(void){ // start sampling asm sei // make atomic ADC_Init(); // Program 11.13 TIOS |= 0x20; // enable OC5 TSCR1 = 0x80; // enable, 4 MHz TCNT TIE |= 0x20; // Arm output compare 5 TFLG1 = 0x20; // Initially clear C5F TC3 = TCNT+50; // First one right away asm cli } //Program 15.3. Real time data acquisition with a simple digital filter, Equation 4. // 9S12C32 C implementation, interrupts at a frequency of fs unsigned short x,y[2]; // y[0] is y(n) current filter output // y[1] is y(n-1) filter output 1 sample ago void interrupt 13 TC5handler(void){ TFLG1 = 0x20; // ack OC5F TC5 = TC5+PERIOD; // Executed every 1/fs y[1] = y[0]; // shift MACQ data x = ADC_In(CHANNEL); // new data y[0] = (x+y[1])/2; } void DAS_Init(void){ // start sampling asm sei // make atomic ADC_Init(); // Program 11.13 TIOS |= 0x20; // enable OC5 TSCR1 = 0x80; // enable, 4 MHz TCNT TIE |= 0x20; // Arm output compare 5 TFLG1 = 0x20; // Initially clear C5F TC3 = TCNT+50; // First one right away asm cli } // Program 15.5. Real time data acquisition with a simple IIR digital filter, Equation 5. unsigned char Median(unsigned char u1,unsigned char u2,unsigned char u3){ unsigned char result; if(u1>u2) if(u2>u3) result = u2; // u1>u2,u2>u3 u1>u2>u3 else if(u1>u3) result = u3; // u1>u2,u3>u2,u1>u3 u1>u3>u2 else result = u1; // u1>u2,u3>u2,u3>u1 u3>u1>u2 else if(u3>u2) result = u2; // u2>u1,u3>u2 u3>u2>u1 else if(u1>u3) result = u1; // u2>u1,u2>u3,u1>u3 u2>u1>u3 else result = u3; // u2>u1,u2>u3,u3>u1 u2>u3>u1 return(result); } unsigned char x[3],y; // x[0] is x(n) the current sample // x[1] is x(n-1) the sample 1/fs ago // x[2] is x(n-2) the sample 2/fs ago void sample(void){ x[2] = x[1]; // shift MACQ data x[1] = x[0]; x[0] = ADC_In(0); // new data from channel 0 y=median(x[0],x[1],x[2]); } //Program 15.6: The median filter is an example of a nonlinear filter. // 9S12C32 C implementation unsigned short x[3],y[3]; // x[0] is x(n) current sample // x[1] is x(n-1) 1 sample ago // x[2] is x(n-2) 2 samples ago // y[0] is y(n) current filter output // y[1] is y(n-1) filter out 1 ago // y[2] is y(n-2) filter out 2 ago void interrupt 13 TC5handler(void){ TFLG1 = 0x20; // ack C5F TC5 = TC5+16667; // 240Hz y[2]=y[1]; y[1]=y[0]; // shift MACQ x[2]=x[1]; x[1]=x[0]; x[0] = ADC_In(CHANNEL); // new data y[0]=(113*(x[0]+x[2])-98*y[2])>>7; } // Program 15.7. Real time data acquisition with a 60 Hz notch digital filter, Equation 58. //*****************old programs from first edition****************** #include "FILTER.H" // prototype file for your filter void Collect(void){ short data; data = ADC_In(0); // sample Fifo_Put(data); } void main(void){ short x,y; // filter input/output LCD_Init(); Filter_Init(100,1000,&Collect); // notch at 100 Hz, sampling at 1000 Hz for(;;){ while(Fifo_Get(&x)==0){}; // wait for input y = Filter(x); // execute filter LCD_Display(y); // show results } } //Program 15.8. Example application of the real-time DAS and filter. // Program 15.1. Real time data acquisition with a simple digital filter, Equation 2. // MC68HC812A4 #define Rate 2000 #define OC5 0x20 #pragma interrupt_handler TOC5handler() void TOC5handler(void){ TFLG1=OC5; // ack OC5F TC5=TC5+Rate; // Executed every 1 ms x[1]=x[0]; // shift MACQ data x[0] = A2D(channel); // new data y=(x[0]+x[1])>>1;} void ritual(void) { asm(" sei"); // make atomic TIOS|=OC5; // enable OC5 TSCR|=0x80; // enable TMSK2=0x32; // 500 ns clock TMSK1|=OC5; // Arm output compare 5 x[0] = x[1] = 0; TFLG1=OC5; // Initially clear C5F TC5=TCNT+Rate; // First one in 1 ms asm(" cli"); } // Program 15.2. Real time data acquisition with a simple digital filter, Equation 3. // MC68HC812A4 #define OC5 0x20 #pragma interrupt_handler TOC5handler() void TOC5handler(void){ unsigned int i; TFLG1=OC5; // ack OC5F TC5=TC5+5556; // fs=360Hz for(i=5;i>0;i++) x[i]=x[i-1]; // shift MACQ data x[0] = A2D(channel); // new data y=(x[0]+x[1]+x[2]+x[3]+x[4]+x[5])/6;} void ritual(void) { asm(" sei"); // make atomic TIOS|=OC5; // enable OC5 TSCR|=0x80; // enable TMSK2=0x32; // 500 ns clock TMSK1|=OC5; // Arm output compare 5 x[0]=x[1]=x[2]=x[3]=x[4]=x[5]=0; TFLG1=OC5; // Initially clear C5F TC5=TCNT+5556; asm(" cli"); } // Program 15.3. Real time data acquisition with a simple digital filter, Equation 4. // MC68HC812A4 #define OC5 0x20 #pragma interrupt_handler TOC5handler() void TOC5handler(void){ TFLG1=OC5; // ack OC5F TC5=TC5+5556; // fs=360Hz x[3]=x[2]; // shift MACQ data x[2]=x[1]; x[1]=x[0]; x[0] = A2D(channel); // new data y=(x[0]+x[3])>>1;} void ritual(void) { asm(" sei"); // make atomic TIOS|=OC5; // enable OC5 TSCR|=0x80; // enable TMSK2=0x32; // 500 ns clock TMSK1|=OC5; // Arm output compare 5 x[0]=x[1]=x[2]=x[3]=0; TFLG1=OC5; // Initially clear C5F TC5=TCNT+5556; asm(" cli"); } // Program 15.4. Compiler listings for the filter implementation. ; MC68HC812A4, ICC12 ; y=(x[0]+x[3])>>1; ldab _x+3 ; 8-bit x[3] clra ; promote into RegD std -10,x ; save on stack ldab _x ; 8 bit x[0] clra ; promote into RegD addd -10,x ; 16-bit x[0]+x[3] asra rolb ; 16-bit shift stab _y ; demote to 8 bit // Program 15.5. Real time data acquisition with a simple digital filter, Equation 5. // MC68HC812A4 #define Rate 2000 #define OC5 0x20 #pragma interrupt_handler TOC5handler() void TOC5handler(void){ TFLG1=OC5; // ack OC5F TC5=TC5+Rate; // Executed at fs y[1]=y[0]; // shift MACQ data x = A2D(channel); // new data y[0]=(x+y[1])>>1;} // 16-bit void ritual(void) { asm(" sei"); // make atomic TIOS|=OC5; // enable OC5 TSCR|=0x80; // enable TMSK2=0x32; // 500 ns clock TMSK1|=OC5; // Arm output compare 5 y[0] = y[1] = 0; TFLG1=OC5; // Initially clear C5F TC5=TCNT+Rate; // First one in 1 ms asm(" cli"); } // Program 15.6: The median filter is an example of a nonlinear filter. unsigned char Median(unsigned char u1,unsigned char u2,unsigned char u3){ unsigned char result; if(u1>u2) if(u2>u3) result=u2; // u1>u2,u2>u3 u1>u2>u3 else if(u1>u3) result=u3; // u1>u2,u3>u2,u1>u3 u1>u3>u2 else result=u1; // u1>u2,u3>u2,u3>u1 u3>u1>u2 else if(u3>u2) result=u2; // u2>u1,u3>u2 u3>u2>u1 else if(u1>u3) result=u3; // u2>u1,u2>u3,u1>u3 u2>u1>u3 else result=u1; // u2>u1,u2>u3,u3>u1 u2>u3>u1 return(result):} unsigned char x[3],y; // x[0] is x(n) the current sample // x[1] is x(n-1) the sample 1/fs ago // x[2] is x(n-2) the sample 2/fs ago void sample(void){ x[2]=x[1]; // shift MACQ data x[1]=x[0]; x[0] = A2D(0); // new data from channel 0 y=median(x[0],x[1],x[2]); // Program 15.7. Real time data acquisition with a 60 Hz notch digital filter, Equation 58. // MC68HC812A4 #define OC5 0x20 #pragma interrupt_handler TOC5handler() void TOC5handler(void){ TFLG1=OC5; // ack OC5F TC5=TC5+8333; // fs=240Hz y[2]=y[1]; y[1]=y[0]; // shift MACQ x[2]=x[1]; x[1]=x[0]; x[0] = A2D(channel); // new data y[0]=(113*(x[0]+x[2])-98*y[2])>>7;} void ritual(void) { asm(" sei"); // make atomic TIOS|=OC5; // enable OC5 TSCR|=0x80; // enable TMSK2=0x32; // 500 ns clock TMSK1|=OC5; // Arm output compare 5 y[0]=y[1]=y[2]=x[0]=x[1]=x[2]=0; TFLG1=OC5; // Initially clear C5F TC5=TCNT+8333; asm(" cli"); }