00001 /* Simple Frequency meter. 00002 Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. 00003 Written by Stephane Carrez (stcarrez@nerim.fr) 00004 00005 This file is free software; you can redistribute it and/or modify it 00006 under the terms of the GNU General Public License as published by the 00007 Free Software Foundation; either version 2, or (at your option) any 00008 later version. 00009 00010 In addition to the permissions in the GNU General Public License, the 00011 Free Software Foundation gives you unlimited permission to link the 00012 compiled version of this file with other programs, and to distribute 00013 those programs without any restriction coming from the use of this 00014 file. (The General Public License restrictions do apply in other 00015 respects; for example, they cover modification of the file, and 00016 distribution when not linked into another program.) 00017 00018 This file is distributed in the hope that it will be useful, but 00019 WITHOUT ANY WARRANTY; without even the implied warranty of 00020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00021 General Public License for more details. 00022 00023 You should have received a copy of the GNU General Public License 00024 along with this program; see the file COPYING. If not, write to 00025 the Free Software Foundation, 59 Temple Place - Suite 330, 00026 Boston, MA 02111-1307, USA. */ 00027 00050 #include <stdio.h> 00051 #include <sys/param.h> 00052 #include <sys/ports.h> 00053 #include <sys/interrupts.h> 00054 #include <sys/sio.h> 00055 #include <sys/locks.h> 00056 00057 #define TIMER_DIV (8192L) 00058 #define TIMER_TICK (M6811_CPU_E_CLOCK / TIMER_DIV) 00059 00060 /* Setup for a 8Mhz quartz, and prescaler set to 1 00061 (500ns period). */ 00062 #define USEC_PER_TICK (1) 00063 #define USEC_DIVISOR (2) 00064 00065 unsigned short prev_time; 00066 unsigned long dt_sum; 00067 unsigned short dt_count; 00068 00069 unsigned long tick_sum; 00070 unsigned short m_count; 00071 00072 volatile unsigned char new_measure = 0; 00073 00074 void input_capture_interrupt (void) __attribute__((interrupt)); 00075 void timer_overflow_interrupt (void) __attribute__((interrupt)); 00076 00077 #ifdef USE_INTERRUPT_TABLE 00078 00079 /* Interrupt table used to connect our timer_interrupt handler. 00080 00081 Note: the `XXX_handler: foo' notation is a GNU extension which is 00082 used here to ensure correct association of the handler in the struct. 00083 This is why the order of handlers declared below does not follow 00084 the HC11 order. */ 00085 struct interrupt_vectors __attribute__((section(".vectors"))) vectors = 00086 { 00087 res0_handler: fatal_interrupt, /* res0 */ 00088 res1_handler: fatal_interrupt, 00089 res2_handler: fatal_interrupt, 00090 res3_handler: fatal_interrupt, 00091 res4_handler: fatal_interrupt, 00092 res5_handler: fatal_interrupt, 00093 res6_handler: fatal_interrupt, 00094 res7_handler: fatal_interrupt, 00095 res8_handler: fatal_interrupt, 00096 res9_handler: fatal_interrupt, 00097 res10_handler: fatal_interrupt, /* res 10 */ 00098 sci_handler: fatal_interrupt, /* sci */ 00099 spi_handler: fatal_interrupt, /* spi */ 00100 acc_overflow_handler: fatal_interrupt, /* acc overflow */ 00101 acc_input_handler: fatal_interrupt, 00102 output5_handler: fatal_interrupt, /* out compare 5 */ 00103 output4_handler: fatal_interrupt, /* out compare 4 */ 00104 output3_handler: fatal_interrupt, /* out compare 3 */ 00105 output2_handler: fatal_interrupt, /* out compare 2 */ 00106 output1_handler: fatal_interrupt, /* out compare 1 */ 00107 capture3_handler: fatal_interrupt, /* in capt 3 */ 00108 capture2_handler: fatal_interrupt, /* in capt 2 */ 00109 rtii_handler: fatal_interrupt, 00110 irq_handler: fatal_interrupt, /* IRQ */ 00111 xirq_handler: fatal_interrupt, /* XIRQ */ 00112 swi_handler: fatal_interrupt, /* swi */ 00113 illegal_handler: fatal_interrupt, /* illegal */ 00114 cop_fail_handler: fatal_interrupt, 00115 cop_clock_handler: fatal_interrupt, 00116 00117 /* What we really need. */ 00118 capture1_handler: input_capture_interrupt, /* in capt 1 */ 00119 timer_overflow_handler: timer_overflow_interrupt, 00120 reset_handler: _start 00121 }; 00122 00123 #endif 00124 00125 void __attribute__((interrupt)) 00126 input_capture_interrupt (void) 00127 { 00128 unsigned short t; 00129 unsigned short dt; 00130 00131 t = get_input_capture_1 (); 00132 if (t > prev_time) 00133 { 00134 dt = t - prev_time; 00135 dt_sum += dt; 00136 dt_count++; 00137 } 00138 prev_time = t; 00139 _io_ports[M6811_TFLG1] |= M6811_IC1F; 00140 } 00141 00142 void __attribute__((interrupt)) 00143 timer_overflow_interrupt (void) 00144 { 00145 static unsigned char nr_overflow = 100; 00146 00147 nr_overflow--; 00148 if (nr_overflow == 0) 00149 { 00150 tick_sum = dt_sum; 00151 m_count = dt_count; 00152 dt_sum = 0; 00153 dt_count = 0; 00154 prev_time = 0xffff; 00155 new_measure++; 00156 nr_overflow = 100; 00157 } 00158 _io_ports[M6811_TFLG2] |= M6811_TOF; 00159 } 00160 00161 static void 00162 report_frequency (unsigned long dt, unsigned short cnt) 00163 { 00164 if (cnt) 00165 dt = dt / cnt; 00166 dt = (dt * USEC_PER_TICK) / USEC_DIVISOR; 00167 dt = 1000000000L / dt; 00168 printf ("\rP: %ld HZ ", dt / 1000); 00169 } 00170 00171 int 00172 main () 00173 { 00174 lock (); 00175 serial_init (); 00176 00177 set_interrupt_handler (TIMER_INPUT1_VECTOR, input_capture_interrupt); 00178 set_interrupt_handler (TIMER_OVERFLOW_VECTOR, timer_overflow_interrupt); 00179 00180 _io_ports[M6811_TMSK2] = M6811_TOI; 00181 _io_ports[M6811_TCTL2] = M6811_EDG1B | M6811_EDG2B | M6811_EDG3B; 00182 _io_ports[M6811_TMSK1] = M6811_IC1I; 00183 new_measure = 0; 00184 prev_time = 0xffff; 00185 unlock (); 00186 00187 while (1) 00188 { 00189 while (new_measure == 0) 00190 continue; 00191 00192 new_measure = 0; 00193 report_frequency (tick_sum, m_count); 00194 } 00195 }