InterruptIn style DigitalIn debounced with callbacks for pin state change and pin state hold.
Fork of PinDetect by
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 bool _holdRepeat; 00144 FunctionPointer _callbackAsserted; 00145 FunctionPointer _callbackDeasserted; 00146 FunctionPointer _callbackAssertedHeld; 00147 FunctionPointer _callbackDeassertedHeld; 00148 00149 /** initialise class 00150 * 00151 * @param PinName p is a valid pin that supports DigitalIn 00152 * @param PinMode m The mode the DigitalIn should use. 00153 */ 00154 void init(PinName p, PinMode m) { 00155 _sampleTime = PINDETECT_SAMPLE_PERIOD; 00156 _samplesTillAssert = PINDETECT_ASSERT_COUNT; 00157 _samplesTillHeld = 0; 00158 _samplesTillAssertReload = PINDETECT_ASSERT_COUNT; 00159 _samplesTillHeldReload = PINDETECT_HOLD_COUNT; 00160 _assertValue = PINDETECT_PIN_ASSTERED; 00161 _holdRepeat = false; 00162 _in = new DigitalIn( p ); 00163 _in->mode( m ); 00164 _prevState = _in->read(); 00165 _ticker = new Ticker; 00166 } 00167 00168 public: 00169 00170 friend class Ticker; 00171 00172 PinDetect() { error("You must supply a PinName"); } 00173 00174 /** PinDetect constructor 00175 * 00176 * By default the PinMode is set to PullDefault. 00177 * 00178 * @see http://mbed.org/handbook/DigitalIn 00179 * @param p PinName is a valid pin that supports DigitalIn 00180 */ 00181 PinDetect(PinName p) { 00182 init( p, PullDefault ); 00183 } 00184 00185 /** PinDetect constructor 00186 * 00187 * @see http://mbed.org/handbook/DigitalIn 00188 * @param PinName p is a valid pin that supports DigitalIn 00189 * @param PinMode m The mode the DigitalIn should use. 00190 */ 00191 PinDetect(PinName p, PinMode m) { 00192 init( p, m ); 00193 } 00194 00195 /** PinDetect destructor 00196 */ 00197 ~PinDetect() { 00198 if ( _ticker ) delete( _ticker ); 00199 if ( _in ) delete( _in ); 00200 } 00201 00202 /** Set whether hold callback is repeatedly invoked while held. 00203 * 00204 * @param bool true to repeat callback, false to call back only once 00205 */ 00206 void setHoldRepeat(bool repeat) { 00207 _holdRepeat = repeat; 00208 } 00209 /** Set the sampling time in microseconds. 00210 * 00211 * @param int The time between pin samples in microseconds. 00212 */ 00213 void setSampleFrequency(int i = PINDETECT_SAMPLE_PERIOD) { 00214 _sampleTime = i; 00215 _prevState = _in->read(); 00216 _ticker->attach_us( this, &PinDetect::isr, _sampleTime ); 00217 } 00218 00219 /** Set the value used as assert. 00220 * 00221 * Defaults to 1 (ie if pin == 1 then pin asserted). 00222 * 00223 * @param int New assert value (1 or 0) 00224 */ 00225 void setAssertValue (int i = PINDETECT_PIN_ASSTERED) { _assertValue = i & 1; } 00226 00227 /** Set the number of continuous samples until assert assumed. 00228 * 00229 * Defaults to 1 (1 * sample frequency). 00230 * 00231 * @param int The number of continuous samples until assert assumed. 00232 */ 00233 void setSamplesTillAssert(int i) { _samplesTillAssertReload = i; } 00234 00235 /** Set the number of continuous samples until held assumed. 00236 * 00237 * Defaults to 50 * sample frequency. 00238 * 00239 * @param int The number of continuous samples until held assumed. 00240 */ 00241 void setSamplesTillHeld(int i) { _samplesTillHeldReload = i; } 00242 00243 /** Set the pin mode. 00244 * 00245 * @see http://mbed.org/projects/libraries/api/mbed/trunk/DigitalInOut#DigitalInOut.mode 00246 * @param PinMode m The mode to pass on to the DigitalIn 00247 */ 00248 void mode(PinMode m) { _in->mode( m ); } 00249 00250 /** Attach a callback function 00251 * 00252 * @code 00253 * 00254 * DigitalOut led1( LED1 ); 00255 * PinDetect pin( p30 ); 00256 * 00257 * void myCallback( void ) { 00258 * led1 = 1; 00259 * }; 00260 * 00261 * main() { 00262 * pin.attach_asserted( &myCallback ); 00263 * } 00264 * 00265 * @endcode 00266 * 00267 * Call this function when a pin is asserted. 00268 * @param function A C function pointer 00269 */ 00270 void attach_asserted(void (*function)(void)) { 00271 _callbackAsserted.attach( function ); 00272 } 00273 00274 /** Attach a callback object/method 00275 * 00276 * @code 00277 * 00278 * class Bar { 00279 * public: 00280 * void myCallback( void ) { led1 = 1; } 00281 * }; 00282 * 00283 * DigitalOut led1( LED1 ); 00284 * PinDetect pin( p30 ); 00285 * Bar bar; 00286 * 00287 * main() { 00288 * pin.attach_asserted( &bar, &Bar::myCallback ); 00289 * } 00290 * 00291 * @endcode 00292 * 00293 * Call this function when a pin is asserted. 00294 * @param object An object that conatins the callback method. 00295 * @param method The method within the object to call. 00296 */ 00297 template<typename T> 00298 void attach_asserted(T *object, void (T::*member)(void)) { 00299 _callbackAsserted.attach( object, member ); 00300 } 00301 00302 /** Attach a callback function 00303 * 00304 * @code 00305 * 00306 * DigitalOut led1( LED1 ); 00307 * PinDetect pin( p30 ); 00308 * 00309 * void myCallback( void ) { 00310 * led1 = 0; 00311 * }; 00312 * 00313 * main() { 00314 * pin.attach_deasserted( &myCallback ); 00315 * } 00316 * 00317 * @endcode 00318 * 00319 * Call this function when a pin is deasserted. 00320 * @param function A C function pointer 00321 */ 00322 void attach_deasserted(void (*function)(void)) { 00323 _callbackDeasserted.attach( function ); 00324 } 00325 00326 /** Attach a callback object/method 00327 * 00328 * @code 00329 * 00330 * class Bar { 00331 * public: 00332 * void myCallback( void ) { led1 = 0; } 00333 * }; 00334 * 00335 * DigitalOut led1( LED1 ); 00336 * PinDetect pin( p30 ); 00337 * Bar bar; 00338 * 00339 * main() { 00340 * pin.attach_deasserted( &bar, &Bar::myCallback ); 00341 * } 00342 * 00343 * @endcode 00344 * 00345 * Call this function when a pin is deasserted. 00346 * @param object An object that conatins the callback method. 00347 * @param method The method within the object to call. 00348 */ 00349 template<typename T> 00350 void attach_deasserted(T *object, void (T::*member)(void)) { 00351 _callbackDeasserted.attach( object, member ); 00352 } 00353 00354 /** Attach a callback function 00355 * 00356 * @code 00357 * 00358 * DigitalOut led2( LED2 ); 00359 * PinDetect pin( p30 ); 00360 * 00361 * void myCallback( void ) { 00362 * led2 = 1; 00363 * }; 00364 * 00365 * main() { 00366 * pin.attach_asserted_held( &myCallback ); 00367 * } 00368 * 00369 * @endcode 00370 * 00371 * Call this function when a pin is asserted and held. 00372 * @param function A C function pointer 00373 */ 00374 void attach_asserted_held(void (*function)(void)) { 00375 _callbackAssertedHeld.attach( function ); 00376 } 00377 00378 /** Attach a callback object/method 00379 * 00380 * @code 00381 * 00382 * class Bar { 00383 * public: 00384 * void myCallback( void ) { led2 = 0; } 00385 * }; 00386 * 00387 * DigitalOut led2( LED2 ); 00388 * PinDetect pin( p30 ); 00389 * Bar bar; 00390 * 00391 * main() { 00392 * pin.attach_asserted_held( &bar, &Bar::myCallback ); 00393 * } 00394 * 00395 * @endcode 00396 * 00397 * Call this function when a pin is asserted and held. 00398 * @param object An object that conatins the callback method. 00399 * @param method The method within the object to call. 00400 */ 00401 template<typename T> 00402 void attach_asserted_held(T *object, void (T::*member)(void)) { 00403 _callbackAssertedHeld.attach( object, member ); 00404 } 00405 00406 /** Attach a callback function 00407 * 00408 * @code 00409 * 00410 * DigitalOut led3( LED3 ); 00411 * PinDetect pin( p30 ); 00412 * 00413 * void myCallback( void ) { 00414 * led3 = 1; 00415 * }; 00416 * 00417 * main() { 00418 * pin.attach_deasserted_held( &myCallback ); 00419 * } 00420 * 00421 * @endcode 00422 * 00423 * Call this function when a pin is deasserted and held. 00424 * @param function A C function pointer 00425 */ 00426 void attach_deasserted_held(void (*function)(void)) { 00427 _callbackDeassertedHeld.attach( function ); 00428 } 00429 00430 /** Attach a callback object/method 00431 * 00432 * @code 00433 * 00434 * class Bar { 00435 * public: 00436 * void myCallback( void ) { led3 = 0; } 00437 * }; 00438 * 00439 * DigitalOut led3( LED3 ); 00440 * PinDetect pin( p30 ); 00441 * Bar bar; 00442 * 00443 * main() { 00444 * pin.attach_deasserted_held( &bar, &Bar::myCallback ); 00445 * } 00446 * 00447 * @endcode 00448 * 00449 * Call this function when a pin is deasserted and held. 00450 * @param object An object that conatins the callback method. 00451 * @param method The method within the object to call. 00452 */ 00453 template<typename T> 00454 void attach_deasserted_held(T *object, void (T::*member)(void)) { 00455 _callbackDeassertedHeld.attach( object, member ); 00456 } 00457 00458 /** operator int() 00459 * 00460 * Read the value of the pin being sampled. 00461 */ 00462 operator int() { return _in->read(); } 00463 00464 protected: 00465 /** The Ticker periodic callback function 00466 */ 00467 void isr(void) { 00468 int currentState = _in->read(); 00469 00470 if ( currentState != _prevState ) { 00471 if ( _samplesTillAssert == 0 ) { 00472 _prevState = currentState; 00473 _samplesTillHeld = _samplesTillHeldReload; 00474 if ( currentState == _assertValue ) 00475 _callbackAsserted.call(); 00476 else 00477 _callbackDeasserted.call(); 00478 } 00479 else { 00480 _samplesTillAssert--; 00481 } 00482 } 00483 else { 00484 _samplesTillAssert = _samplesTillAssertReload; 00485 } 00486 00487 if ( _samplesTillHeld ) { 00488 if ( _prevState == currentState ) { 00489 _samplesTillHeld--; 00490 if ( _samplesTillHeld == 0 ) { 00491 if ( currentState == _assertValue ) 00492 _callbackAssertedHeld.call(); 00493 else 00494 _callbackDeassertedHeld.call(); 00495 if(_holdRepeat) { 00496 _samplesTillHeld = _samplesTillHeldReload; 00497 } 00498 } 00499 } 00500 else { 00501 _samplesTillHeld = 0; 00502 } 00503 } 00504 } 00505 00506 }; 00507 00508 }; // namespace AjK ends. 00509 00510 using namespace AjK; 00511 00512 #endif
Generated on Tue Jul 12 2022 21:18:34 by
