|
1 /* |
|
2 wiring_pulse.c - pulseIn() function |
|
3 Part of Arduino - http://www.arduino.cc/ |
|
4 |
|
5 Copyright (c) 2005-2006 David A. Mellis |
|
6 |
|
7 This library is free software; you can redistribute it and/or |
|
8 modify it under the terms of the GNU Lesser General Public |
|
9 License as published by the Free Software Foundation; either |
|
10 version 2.1 of the License, or (at your option) any later version. |
|
11 |
|
12 This library is distributed in the hope that it will be useful, |
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 Lesser General Public License for more details. |
|
16 |
|
17 You should have received a copy of the GNU Lesser General |
|
18 Public License along with this library; if not, write to the |
|
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
|
20 Boston, MA 02111-1307 USA |
|
21 |
|
22 $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ |
|
23 */ |
|
24 |
|
25 #include "wiring_private.h" |
|
26 #include "pins_arduino.h" |
|
27 |
|
28 /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH |
|
29 * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds |
|
30 * to 3 minutes in length, but must be called at least a few dozen microseconds |
|
31 * before the start of the pulse. */ |
|
32 unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) |
|
33 { |
|
34 // cache the port and bit of the pin in order to speed up the |
|
35 // pulse width measuring loop and achieve finer resolution. calling |
|
36 // digitalRead() instead yields much coarser resolution. |
|
37 uint8_t bit = digitalPinToBitMask(pin); |
|
38 uint8_t port = digitalPinToPort(pin); |
|
39 uint8_t stateMask = (state ? bit : 0); |
|
40 unsigned long width = 0; // keep initialization out of time critical area |
|
41 |
|
42 // convert the timeout from microseconds to a number of times through |
|
43 // the initial loop; it takes 16 clock cycles per iteration. |
|
44 unsigned long numloops = 0; |
|
45 unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; |
|
46 |
|
47 // wait for any previous pulse to end |
|
48 while ((*portInputRegister(port) & bit) == stateMask) |
|
49 if (numloops++ == maxloops) |
|
50 return 0; |
|
51 |
|
52 // wait for the pulse to start |
|
53 while ((*portInputRegister(port) & bit) != stateMask) |
|
54 if (numloops++ == maxloops) |
|
55 return 0; |
|
56 |
|
57 // wait for the pulse to stop |
|
58 while ((*portInputRegister(port) & bit) == stateMask) { |
|
59 if (numloops++ == maxloops) |
|
60 return 0; |
|
61 width++; |
|
62 } |
|
63 |
|
64 // convert the reading to microseconds. The loop has been determined |
|
65 // to be 20 clock cycles long and have about 16 clocks between the edge |
|
66 // and the start of the loop. There will be some error introduced by |
|
67 // the interrupt handlers. |
|
68 return clockCyclesToMicroseconds(width * 21 + 16); |
|
69 } |