InterruptIn style DigitalIn debounced with callbacks for pin state change and pin state hold.
Dependents: AVC_20110423 SimplePIDBot Pushbutton_Debounce_Interrupt FinalProgram ... more
PinDetect.h
00001 /* 00002 Copyright (c) 2010 Andy Kirkham 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 */ 00022 00023 #ifndef AJK_PIN_DETECT_H 00024 #define AJK_PIN_DETECT_H 00025 00026 #ifndef MBED_H 00027 #include "mbed.h" 00028 #endif 00029 00030 #ifndef PINDETECT_PIN_ASSTERED 00031 #define PINDETECT_PIN_ASSTERED 1 00032 #endif 00033 00034 #ifndef PINDETECT_SAMPLE_PERIOD 00035 #define PINDETECT_SAMPLE_PERIOD 20000 00036 #endif 00037 00038 #ifndef PINDETECT_ASSERT_COUNT 00039 #define PINDETECT_ASSERT_COUNT 1 00040 #endif 00041 00042 #ifndef PINDETECT_HOLD_COUNT 00043 #define PINDETECT_HOLD_COUNT 50 00044 #endif 00045 00046 namespace AjK { 00047 00048 /** PinDetect adds mechanical switch debouncing to DigitialIn and interrupt callbacks. 00049 * 00050 * This is done by sampling the specified pin at regular intervals and detecting any 00051 * change of state ( 0 -> 1 or 1 -> 0 ). When a state change is detected the attached 00052 * callback handler is called. Additionally, if the pin stays in the same state after 00053 * a state change for a defined period of time, an extra callback is made allowing a 00054 * program to detect when a "key is pressed and held down" rather than a momentary 00055 * key/switch press. 00056 * 00057 * All parameters are customisable which include:- 00058 * <ul> 00059 * <li> The sampling frequency. </li> 00060 * <li> The number of continuous samples until a state change is detected. </li> 00061 * <li> The number of continuous samples until a key is assumed held after a state change. </li> 00062 * <li> The logic level which is assumed to be asserted (0volts or +volts). </li> 00063 * </ul> 00064 * 00065 * Only callbacks that have been attached will be called by the library. 00066 * 00067 * Example: 00068 * @code 00069 * #include "mbed.h" 00070 * #include "PinDetect.h" 00071 * 00072 * PinDetect pin( p30 ); 00073 * DigitialOut led1( LED1 ); 00074 * DigitialOut led2( LED2 ); 00075 * DigitialOut led3( LED3 ); 00076 * DigitialOut led4( LED4 ); 00077 * 00078 * void keyPressed( void ) { 00079 * led2 = 1; 00080 * led3 = 0; 00081 * led4 = 0; 00082 * } 00083 * 00084 * void keyReleased( void ) { 00085 * led2 = 0; 00086 * led3 = 0; 00087 * led4 = 0; 00088 * } 00089 * 00090 * void keyPressedHeld( void ) { 00091 * led3 = 1; 00092 * } 00093 * 00094 * void keyReleasedHeld( void ) { 00095 * led4 = 1; 00096 * } 00097 * 00098 * int main() { 00099 * 00100 * pin.mode( PullDown ); 00101 * pin.attach_asserted( &keyPressed ); 00102 * pin.attach_deasserted( &keyReleased ); 00103 * pin.attach_asserted_held( &keyPressedHeld ); 00104 * pin.attach_deasserted_held( &keyReleasedHeld ); 00105 * 00106 * // Sampling does not begin until you set a frequency. 00107 * // The default is 20ms. If you want a different frequency 00108 * // then pass the period in microseconds for example, for 10ms :- 00109 * // pin.setSampleFrequency( 10000 ); 00110 * // 00111 * pin.setSampleFrequency(); // Defaults to 20ms. 00112 * 00113 * while( 1 ) { 00114 * led1 = !led1; 00115 * wait( 0.2 ); 00116 * } 00117 * } 00118 * @endcode 00119 * 00120 * This example will flash led1 in a similar to a standard starting program. 00121 * 00122 * Applying a "1" (switch on) to pin 30 will switch on led2, removing the "1" to "0" 00123 * (switch off) led2 goes out. Holding the "switch" at one for one second will switch 00124 * on led3. An unasserted P30 (switched off) will, after one second illuminate led4 00125 * when the deasserted calledback is called. 00126 * 00127 * The above is a very basic introduction. For more details:- 00128 * @see example.h 00129 */ 00130 class PinDetect { 00131 00132 protected: 00133 DigitalIn *_in; 00134 Ticker *_ticker; 00135 int _prevState; 00136 int _currentStateCounter; 00137 int _sampleTime; 00138 int _assertValue; 00139 int _samplesTillAssertReload; 00140 int _samplesTillAssert; 00141 int _samplesTillHeldReload; 00142 int _samplesTillHeld; 00143 FunctionPointer _callbackAsserted; 00144 FunctionPointer _callbackDeasserted; 00145 FunctionPointer _callbackAssertedHeld; 00146 FunctionPointer _callbackDeassertedHeld; 00147 00148 /** initialise class 00149 * 00150 * @param PinName p is a valid pin that supports DigitalIn 00151 * @param PinMode m The mode the DigitalIn should use. 00152 */ 00153 void init(PinName p, PinMode m) { 00154 _sampleTime = PINDETECT_SAMPLE_PERIOD; 00155 _samplesTillAssert = PINDETECT_ASSERT_COUNT; 00156 _samplesTillHeld = 0; 00157 _samplesTillAssertReload = PINDETECT_ASSERT_COUNT; 00158 _samplesTillHeldReload = PINDETECT_HOLD_COUNT; 00159 _assertValue = PINDETECT_PIN_ASSTERED; 00160 00161 _in = new DigitalIn( p ); 00162 _in->mode( m ); 00163 _prevState = _in->read(); 00164 _ticker = new Ticker; 00165 } 00166 00167 public: 00168 00169 friend class Ticker; 00170 00171 PinDetect() { error("You must supply a PinName"); } 00172 00173 /** PinDetect constructor 00174 * 00175 * By default the PinMode is set to PullDown. 00176 * 00177 * @see http://mbed.org/handbook/DigitalIn 00178 * @param p PinName is a valid pin that supports DigitalIn 00179 */ 00180 PinDetect(PinName p) { 00181 init( p, PullDown ); 00182 } 00183 00184 /** PinDetect constructor 00185 * 00186 * @see http://mbed.org/handbook/DigitalIn 00187 * @param PinName p is a valid pin that supports DigitalIn 00188 * @param PinMode m The mode the DigitalIn should use. 00189 */ 00190 PinDetect(PinName p, PinMode m) { 00191 init( p, m ); 00192 } 00193 00194 /** PinDetect destructor 00195 */ 00196 ~PinDetect() { 00197 if ( _ticker ) delete( _ticker ); 00198 if ( _in ) delete( _in ); 00199 } 00200 00201 /** Set the sampling time in microseconds. 00202 * 00203 * @param int The time between pin samples in microseconds. 00204 */ 00205 void setSampleFrequency(int i = PINDETECT_SAMPLE_PERIOD) { 00206 _sampleTime = i; 00207 _prevState = _in->read(); 00208 _ticker->attach_us( this, &PinDetect::isr, _sampleTime ); 00209 } 00210 00211 /** Set the value used as assert. 00212 * 00213 * Defaults to 1 (ie if pin == 1 then pin asserted). 00214 * 00215 * @param int New assert value (1 or 0) 00216 */ 00217 void setAssertValue (int i = PINDETECT_PIN_ASSTERED) { _assertValue = i & 1; } 00218 00219 /** Set the number of continuous samples until assert assumed. 00220 * 00221 * Defaults to 1 (1 * sample frequency). 00222 * 00223 * @param int The number of continuous samples until assert assumed. 00224 */ 00225 void setSamplesTillAssert(int i) { _samplesTillAssertReload = i; } 00226 00227 /** Set the number of continuous samples until held assumed. 00228 * 00229 * Defaults to 50 * sample frequency. 00230 * 00231 * @param int The number of continuous samples until held assumed. 00232 */ 00233 void setSamplesTillHeld(int i) { _samplesTillHeldReload = i; } 00234 00235 /** Set the pin mode. 00236 * 00237 * @see http://mbed.org/projects/libraries/api/mbed/trunk/DigitalInOut#DigitalInOut.mode 00238 * @param PinMode m The mode to pass on to the DigitalIn 00239 */ 00240 void mode(PinMode m) { _in->mode( m ); } 00241 00242 /** Attach a callback function 00243 * 00244 * @code 00245 * 00246 * DigitalOut led1( LED1 ); 00247 * PinDetect pin( p30 ); 00248 * 00249 * void myCallback( void ) { 00250 * led1 = 1; 00251 * }; 00252 * 00253 * main() { 00254 * pin.attach_asserted( &myCallback ); 00255 * } 00256 * 00257 * @endcode 00258 * 00259 * Call this function when a pin is asserted. 00260 * @param function A C function pointer 00261 */ 00262 void attach_asserted(void (*function)(void)) { 00263 _callbackAsserted.attach( function ); 00264 } 00265 00266 /** Attach a callback object/method 00267 * 00268 * @code 00269 * 00270 * class Bar { 00271 * public: 00272 * void myCallback( void ) { led1 = 1; } 00273 * }; 00274 * 00275 * DigitalOut led1( LED1 ); 00276 * PinDetect pin( p30 ); 00277 * Bar bar; 00278 * 00279 * main() { 00280 * pin.attach_asserted( &bar, &Bar::myCallback ); 00281 * } 00282 * 00283 * @endcode 00284 * 00285 * Call this function when a pin is asserted. 00286 * @param object An object that conatins the callback method. 00287 * @param method The method within the object to call. 00288 */ 00289 template<typename T> 00290 void attach_asserted(T *object, void (T::*member)(void)) { 00291 _callbackAsserted.attach( object, member ); 00292 } 00293 00294 /** Attach a callback function 00295 * 00296 * @code 00297 * 00298 * DigitalOut led1( LED1 ); 00299 * PinDetect pin( p30 ); 00300 * 00301 * void myCallback( void ) { 00302 * led1 = 0; 00303 * }; 00304 * 00305 * main() { 00306 * pin.attach_deasserted( &myCallback ); 00307 * } 00308 * 00309 * @endcode 00310 * 00311 * Call this function when a pin is deasserted. 00312 * @param function A C function pointer 00313 */ 00314 void attach_deasserted(void (*function)(void)) { 00315 _callbackDeasserted.attach( function ); 00316 } 00317 00318 /** Attach a callback object/method 00319 * 00320 * @code 00321 * 00322 * class Bar { 00323 * public: 00324 * void myCallback( void ) { led1 = 0; } 00325 * }; 00326 * 00327 * DigitalOut led1( LED1 ); 00328 * PinDetect pin( p30 ); 00329 * Bar bar; 00330 * 00331 * main() { 00332 * pin.attach_deasserted( &bar, &Bar::myCallback ); 00333 * } 00334 * 00335 * @endcode 00336 * 00337 * Call this function when a pin is deasserted. 00338 * @param object An object that conatins the callback method. 00339 * @param method The method within the object to call. 00340 */ 00341 template<typename T> 00342 void attach_deasserted(T *object, void (T::*member)(void)) { 00343 _callbackDeasserted.attach( object, member ); 00344 } 00345 00346 /** Attach a callback function 00347 * 00348 * @code 00349 * 00350 * DigitalOut led2( LED2 ); 00351 * PinDetect pin( p30 ); 00352 * 00353 * void myCallback( void ) { 00354 * led2 = 1; 00355 * }; 00356 * 00357 * main() { 00358 * pin.attach_asserted_held( &myCallback ); 00359 * } 00360 * 00361 * @endcode 00362 * 00363 * Call this function when a pin is asserted and held. 00364 * @param function A C function pointer 00365 */ 00366 void attach_asserted_held(void (*function)(void)) { 00367 _callbackAssertedHeld.attach( function ); 00368 } 00369 00370 /** Attach a callback object/method 00371 * 00372 * @code 00373 * 00374 * class Bar { 00375 * public: 00376 * void myCallback( void ) { led2 = 0; } 00377 * }; 00378 * 00379 * DigitalOut led2( LED2 ); 00380 * PinDetect pin( p30 ); 00381 * Bar bar; 00382 * 00383 * main() { 00384 * pin.attach_asserted_held( &bar, &Bar::myCallback ); 00385 * } 00386 * 00387 * @endcode 00388 * 00389 * Call this function when a pin is asserted and held. 00390 * @param object An object that conatins the callback method. 00391 * @param method The method within the object to call. 00392 */ 00393 template<typename T> 00394 void attach_asserted_held(T *object, void (T::*member)(void)) { 00395 _callbackAssertedHeld.attach( object, member ); 00396 } 00397 00398 /** Attach a callback function 00399 * 00400 * @code 00401 * 00402 * DigitalOut led3( LED3 ); 00403 * PinDetect pin( p30 ); 00404 * 00405 * void myCallback( void ) { 00406 * led3 = 1; 00407 * }; 00408 * 00409 * main() { 00410 * pin.attach_deasserted_held( &myCallback ); 00411 * } 00412 * 00413 * @endcode 00414 * 00415 * Call this function when a pin is deasserted and held. 00416 * @param function A C function pointer 00417 */ 00418 void attach_deasserted_held(void (*function)(void)) { 00419 _callbackDeassertedHeld.attach( function ); 00420 } 00421 00422 /** Attach a callback object/method 00423 * 00424 * @code 00425 * 00426 * class Bar { 00427 * public: 00428 * void myCallback( void ) { led3 = 0; } 00429 * }; 00430 * 00431 * DigitalOut led3( LED3 ); 00432 * PinDetect pin( p30 ); 00433 * Bar bar; 00434 * 00435 * main() { 00436 * pin.attach_deasserted_held( &bar, &Bar::myCallback ); 00437 * } 00438 * 00439 * @endcode 00440 * 00441 * Call this function when a pin is deasserted and held. 00442 * @param object An object that conatins the callback method. 00443 * @param method The method within the object to call. 00444 */ 00445 template<typename T> 00446 void attach_deasserted_held(T *object, void (T::*member)(void)) { 00447 _callbackDeassertedHeld.attach( object, member ); 00448 } 00449 00450 /** operator int() 00451 * 00452 * Read the value of the pin being sampled. 00453 */ 00454 operator int() { return _in->read(); } 00455 00456 protected: 00457 /** The Ticker periodic callback function 00458 */ 00459 void isr(void) { 00460 int currentState = _in->read(); 00461 00462 if ( currentState != _prevState ) { 00463 if ( _samplesTillAssert == 0 ) { 00464 _prevState = currentState; 00465 _samplesTillHeld = _samplesTillHeldReload; 00466 if ( currentState == _assertValue ) 00467 _callbackAsserted.call(); 00468 else 00469 _callbackDeasserted.call(); 00470 } 00471 else { 00472 _samplesTillAssert--; 00473 } 00474 } 00475 else { 00476 _samplesTillAssert = _samplesTillAssertReload; 00477 } 00478 00479 if ( _samplesTillHeld ) { 00480 if ( _prevState == currentState ) { 00481 _samplesTillHeld--; 00482 if ( _samplesTillHeld == 0 ) { 00483 if ( currentState == _assertValue ) 00484 _callbackAssertedHeld.call(); 00485 else 00486 _callbackDeassertedHeld.call(); 00487 } 00488 } 00489 else { 00490 _samplesTillHeld = 0; 00491 } 00492 } 00493 } 00494 00495 }; 00496 00497 }; // namespace AjK ends. 00498 00499 using namespace AjK; 00500 00501 #endif
Generated on Tue Jul 12 2022 16:27:44 by 1.7.2