00001
00023 #if __GCC__
00024 #include <avr/io.h>
00025 #include <avr/signal.h>
00026 #else
00027 #include <stdio.h>
00028 #include <inavr.h>
00029 #define ENABLE_BIT_DEFINITIONS
00030 #include <iom64.h>
00031 #endif
00032 #include "icp.h"
00033
00034
00035
00036
00037 #define ICP_PIN PIND
00038 #define ICP_PORT PORTD
00039 #define ICP_DDR DDRD
00040 #define ICP_BIT PD4
00041
00042
00043
00044
00045 #define ICP_OCR OCR1A
00046 #define ICP_OC_IE OCIE1A
00047 #define ICP_OC_IF OCF1A
00048 #define ICP_IE TICIE1
00049 #define ICP_IF ICF1
00050 #define ICP_CTL_A TCCR1A
00051 #define ICP_CTL TCCR1B
00052 #define ICP_SENSE ICES1
00053 #define ICP_PRESCALE ((0 << CS12) | (0 << CS11) | (1 << CS10))
00054
00055 #define ICP_START_SENSE (1 << ICP_SENSE)
00056
00065 typedef unsigned int icp_timer_t;
00066 icp_timer_t icp_start_time, icp_stop_time;
00067 icp_timer_t icp_period;
00068
00076 icp_sample_t icp_rx_q[ICP_RX_QSIZE];
00077
00088 unsigned char icp_rx_tail;
00089 #if !ICP_ANALOG
00090 unsigned char icp_rx_head;
00091 #endif
00092
00093 #if ICP_ANALOG
00094
00102 icp_total_t icp_total;
00103 #endif
00104
00117 #if __GCC__
00118 __inline__
00119 #else
00120 #pragma inline
00121 #endif
00122 static icp_sample_t icp_duty_compute(icp_timer_t pulsewidth, icp_timer_t period)
00123 {
00124 icp_sample_t r, mask;
00125
00126 mask = ICP_SCALE >> 1;
00127 r = 0;
00128 do
00129 {
00130 period >>= 1;
00131 if (pulsewidth >= period)
00132 {
00133 r |= mask;
00134 pulsewidth -= period;
00135 }
00136 mask >>= 1;
00137 } while (pulsewidth != 0 && mask != 0);
00138 return(r);
00139 }
00140
00146 #if __GCC__
00147 __inline__
00148 #else
00149 #pragma inline
00150 #endif
00151 static void icp_enq(icp_sample_t sample)
00152 {
00153 unsigned char t;
00154
00155 t = icp_rx_tail;
00156 #if ICP_ANALOG
00157 icp_total += sample - icp_rx_q[t];
00158 #endif
00159 icp_rx_q[t] = sample;
00160 if (++t >= ICP_RX_QSIZE)
00161 t = 0;
00162 #if !ICP_ANALOG
00163 if (t != icp_rx_head)
00164 #endif
00165 icp_rx_tail = t;
00166 return;
00167 }
00168
00178 #if __GCC__
00179 SIGNAL(SIG_OUTPUT_COMPARE1A)
00180 #else
00181 #pragma vector=TIMER1_COMPA_vect
00182 __interrupt void TIMER1_COMPA(void)
00183 #endif
00184 {
00185 icp_sample_t sample;
00186
00187 ICP_OCR += icp_period;
00188 sample = 0;
00189 if ((ICP_CTL & (1 << ICP_SENSE)) != ICP_START_SENSE)
00190 sample = ICP_SCALE - 1;
00191
00192 icp_enq(sample);
00193
00194 return;
00195 }
00196
00202 #if __GCC__
00203 SIGNAL(SIG_INPUT_CAPTURE1)
00204 #else
00205 #pragma vector=TIMER1_CAPT_vect
00206 __interrupt void TIMER1_CAPT(void)
00207 #endif
00208 {
00209 icp_timer_t icr, delta;
00210 unsigned char tccr1b;
00211
00212
00213
00214
00215
00216
00217 icr = ICR1;
00218
00219 do
00220 {
00221 tccr1b = ICP_CTL;
00222 ICP_CTL = tccr1b ^ (1 << ICP_SENSE);
00223
00224
00225
00226
00227
00228 if ((tccr1b & (1 << ICP_SENSE)) == ICP_START_SENSE)
00229 {
00230
00231
00232
00233
00234 icp_period = icr - icp_start_time;
00235 delta = icp_stop_time - icp_start_time;
00236 icp_start_time = icr;
00237
00238
00239
00240
00241
00242
00243
00244 ICP_OCR = icr + icp_period + 1;
00245 TIFR = (1 << ICP_OC_IF);
00246
00247
00248
00249
00250 icp_enq(icp_duty_compute(delta,icp_period));
00251
00252
00253
00254
00255
00256
00257
00258
00259 if ((ICP_PIN & (1 << ICP_BIT)) || (TIFR & (1 << ICP_IF)))
00260 break;
00261 }
00262 else
00263 {
00264
00265
00266
00267
00268
00269 icp_stop_time = icr;
00270
00271
00272
00273
00274
00275
00276 if ((!(ICP_PIN & (1 << ICP_BIT))) || (TIFR & (1 << ICP_IF)))
00277 break;
00278 }
00279
00280
00281
00282
00283
00284
00285 } while (1);
00286
00287 return;
00288 }
00289
00297 icp_sample_t
00298 icp_rx(void)
00299 {
00300 icp_sample_t r;
00301
00302 #if ICP_ANALOG
00303 r = icp_total / ICP_RX_QSIZE;
00304 #else
00305 unsigned char h;
00306
00307 h = icp_rx_head;
00308 if (h == icp_rx_tail)
00309 r = (icp_sample_t)-1;
00310 else
00311 {
00312 r = icp_rx_q[h];
00313 if (++h >= ICP_RX_QSIZE)
00314 h = 0;
00315 icp_rx_head = h;
00316 }
00317 #endif
00318
00319 return(r);
00320 }
00321
00327 void
00328 icp_init(void)
00329 {
00330
00331
00332
00333 ICP_CTL_A = 0;
00334
00335
00336
00337
00338
00339 ICP_OCR = 0;
00340
00341
00342
00343
00344 ICP_CTL = ICP_START_SENSE | ICP_PRESCALE;
00345
00346
00347
00348
00349
00350 TIMSK |= (1 << ICP_IE) | (1 << ICP_OC_IE);
00351
00352 return;
00353 }