Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ExioBufferedPinDetect.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 /* 00024 * 2016.11.5 Customized for MCP23S17 Buffered Input by ryood 00025 */ 00026 00027 #ifndef AJK_PIN_DETECT_H 00028 #define AJK_PIN_DETECT_H 00029 00030 #ifndef MBED_H 00031 #include "mbed.h" 00032 #endif 00033 00034 #include "ExioBufferedIn.h" 00035 00036 #ifndef PINDETECT_PIN_ASSTERED 00037 #define PINDETECT_PIN_ASSTERED 1 00038 #endif 00039 00040 #ifndef PINDETECT_SAMPLE_PERIOD 00041 #define PINDETECT_SAMPLE_PERIOD 20000 00042 #endif 00043 00044 #ifndef PINDETECT_ASSERT_COUNT 00045 #define PINDETECT_ASSERT_COUNT 1 00046 #endif 00047 00048 #ifndef PINDETECT_HOLD_COUNT 00049 #define PINDETECT_HOLD_COUNT 50 00050 #endif 00051 00052 namespace AjK { 00053 00054 /** PinDetect adds mechanical switch debouncing to DigitialIn and interrupt callbacks. 00055 * 00056 * This is done by sampling the specified pin at regular intervals and detecting any 00057 * change of state ( 0 -> 1 or 1 -> 0 ). When a state change is detected the attached 00058 * callback handler is called. Additionally, if the pin stays in the same state after 00059 * a state change for a defined period of time, an extra callback is made allowing a 00060 * program to detect when a "key is pressed and held down" rather than a momentary 00061 * key/switch press. 00062 * 00063 * All parameters are customisable which include:- 00064 * <ul> 00065 * <li> The sampling frequency. </li> 00066 * <li> The number of continuous samples until a state change is detected. </li> 00067 * <li> The number of continuous samples until a key is assumed held after a state change. </li> 00068 * <li> The logic level which is assumed to be asserted (0volts or +volts). </li> 00069 * </ul> 00070 * 00071 * Only callbacks that have been attached will be called by the library. 00072 * 00073 * Example: 00074 * @code 00075 * #include "mbed.h" 00076 * #include "PinDetect.h" 00077 * 00078 * PinDetect pin( p30 ); 00079 * DigitialOut led1( LED1 ); 00080 * DigitialOut led2( LED2 ); 00081 * DigitialOut led3( LED3 ); 00082 * DigitialOut led4( LED4 ); 00083 * 00084 * void keyPressed( void ) { 00085 * led2 = 1; 00086 * led3 = 0; 00087 * led4 = 0; 00088 * } 00089 * 00090 * void keyReleased( void ) { 00091 * led2 = 0; 00092 * led3 = 0; 00093 * led4 = 0; 00094 * } 00095 * 00096 * void keyPressedHeld( void ) { 00097 * led3 = 1; 00098 * } 00099 * 00100 * void keyReleasedHeld( void ) { 00101 * led4 = 1; 00102 * } 00103 * 00104 * int main() { 00105 * 00106 * pin.mode( PullDown ); 00107 * pin.attach_asserted( &keyPressed ); 00108 * pin.attach_deasserted( &keyReleased ); 00109 * pin.attach_asserted_held( &keyPressedHeld ); 00110 * pin.attach_deasserted_held( &keyReleasedHeld ); 00111 * 00112 * // Sampling does not begin until you set a frequency. 00113 * // The default is 20ms. If you want a different frequency 00114 * // then pass the period in microseconds for example, for 10ms :- 00115 * // pin.setSampleFrequency( 10000 ); 00116 * // 00117 * pin.setSampleFrequency(); // Defaults to 20ms. 00118 * 00119 * while( 1 ) { 00120 * led1 = !led1; 00121 * wait( 0.2 ); 00122 * } 00123 * } 00124 * @endcode 00125 * 00126 * This example will flash led1 in a similar to a standard starting program. 00127 * 00128 * Applying a "1" (switch on) to pin 30 will switch on led2, removing the "1" to "0" 00129 * (switch off) led2 goes out. Holding the "switch" at one for one second will switch 00130 * on led3. An unasserted P30 (switched off) will, after one second illuminate led4 00131 * when the deasserted calledback is called. 00132 * 00133 * The above is a very basic introduction. For more details:- 00134 * @see example.h 00135 */ 00136 class ExioBufferedPinDetect { 00137 00138 protected: 00139 //DigitalIn *_in; 00140 ExioBufferedIn *_in; 00141 Ticker *_ticker; 00142 int _prevState; 00143 int _currentStateCounter; 00144 int _sampleTime; 00145 int _assertValue; 00146 int _samplesTillAssertReload; 00147 int _samplesTillAssert; 00148 int _samplesTillHeldReload; 00149 int _samplesTillHeld; 00150 FunctionPointer _callbackAsserted; 00151 FunctionPointer _callbackDeasserted; 00152 FunctionPointer _callbackAssertedHeld; 00153 FunctionPointer _callbackDeassertedHeld; 00154 00155 /** initialise class 00156 * 00157 * @param PinName p is a valid pin that supports DigitalIn 00158 * @param PinMode m The mode the DigitalIn should use. 00159 */ 00160 /* 00161 void init(PinName p, PinMode m) { 00162 _sampleTime = PINDETECT_SAMPLE_PERIOD; 00163 _samplesTillAssert = PINDETECT_ASSERT_COUNT; 00164 _samplesTillHeld = 0; 00165 _samplesTillAssertReload = PINDETECT_ASSERT_COUNT; 00166 _samplesTillHeldReload = PINDETECT_HOLD_COUNT; 00167 _assertValue = PINDETECT_PIN_ASSTERED; 00168 00169 _in = new DigitalIn( p ); 00170 _in->mode( m ); 00171 _prevState = _in->read(); 00172 _ticker = new Ticker; 00173 } 00174 */ 00175 void init(ExioInBuffer* buffer, int pin, PinMode m) { 00176 _sampleTime = PINDETECT_SAMPLE_PERIOD; 00177 _samplesTillAssert = PINDETECT_ASSERT_COUNT; 00178 _samplesTillHeld = 0; 00179 _samplesTillAssertReload = PINDETECT_ASSERT_COUNT; 00180 _samplesTillHeldReload = PINDETECT_HOLD_COUNT; 00181 _assertValue = PINDETECT_PIN_ASSTERED; 00182 00183 _in = new ExioBufferedIn( buffer, pin ); 00184 _in->mode( m ); 00185 _prevState = _in->read(); 00186 _ticker = new Ticker; 00187 } 00188 00189 public: 00190 00191 friend class Ticker; 00192 00193 ExioBufferedPinDetect() { error("You must construct ExioBufferedDetect with params"); } 00194 00195 /** PinDetect constructor 00196 * 00197 * By default the PinMode is set to PullDown. 00198 * 00199 * @see http://mbed.org/handbook/DigitalIn 00200 * @param p PinName is a valid pin that supports DigitalIn 00201 */ 00202 /* 00203 PinDetect(PinName p) { 00204 init( p, PullDown ); 00205 } 00206 */ 00207 ExioBufferedPinDetect(ExioInBuffer* buffer, int pin) { 00208 init( buffer, pin, PullUp ); 00209 } 00210 00211 /** PinDetect constructor 00212 * 00213 * @see http://mbed.org/handbook/DigitalIn 00214 * @param PinName p is a valid pin that supports DigitalIn 00215 * @param PinMode m The mode the DigitalIn should use. 00216 */ 00217 /* 00218 PinDetect(PinName p, PinMode m) { 00219 init( p, m ); 00220 } 00221 */ 00222 ExioBufferedPinDetect(ExioInBuffer* buffer, int pin, PinMode m) { 00223 init( buffer, pin, m ); 00224 } 00225 00226 /** PinDetect destructor 00227 */ 00228 ~ExioBufferedPinDetect() { 00229 if ( _ticker ) delete( _ticker ); 00230 if ( _in ) delete( _in ); 00231 } 00232 00233 /** Set the sampling time in microseconds. 00234 * 00235 * @param int The time between pin samples in microseconds. 00236 */ 00237 void setSampleFrequency(int i = PINDETECT_SAMPLE_PERIOD) { 00238 _sampleTime = i; 00239 _prevState = _in->read(); 00240 _ticker->attach_us( this, &ExioBufferedPinDetect::isr, _sampleTime ); 00241 } 00242 00243 /** Set the value used as assert. 00244 * 00245 * Defaults to 1 (ie if pin == 1 then pin asserted). 00246 * 00247 * @param int New assert value (1 or 0) 00248 */ 00249 void setAssertValue (int i = PINDETECT_PIN_ASSTERED) { _assertValue = i & 1; } 00250 00251 /** Set the number of continuous samples until assert assumed. 00252 * 00253 * Defaults to 1 (1 * sample frequency). 00254 * 00255 * @param int The number of continuous samples until assert assumed. 00256 */ 00257 void setSamplesTillAssert(int i) { _samplesTillAssertReload = i; } 00258 00259 /** Set the number of continuous samples until held assumed. 00260 * 00261 * Defaults to 50 * sample frequency. 00262 * 00263 * @param int The number of continuous samples until held assumed. 00264 */ 00265 void setSamplesTillHeld(int i) { _samplesTillHeldReload = i; } 00266 00267 /** Set the pin mode. 00268 * 00269 * @see http://mbed.org/projects/libraries/api/mbed/trunk/DigitalInOut#DigitalInOut.mode 00270 * @param PinMode m The mode to pass on to the DigitalIn 00271 */ 00272 void mode(PinMode m) { _in->mode( m ); } 00273 00274 /** Attach a callback function 00275 * 00276 * @code 00277 * 00278 * DigitalOut led1( LED1 ); 00279 * PinDetect pin( p30 ); 00280 * 00281 * void myCallback( void ) { 00282 * led1 = 1; 00283 * }; 00284 * 00285 * main() { 00286 * pin.attach_asserted( &myCallback ); 00287 * } 00288 * 00289 * @endcode 00290 * 00291 * Call this function when a pin is asserted. 00292 * @param function A C function pointer 00293 */ 00294 void attach_asserted(void (*function)(void)) { 00295 _callbackAsserted.attach( function ); 00296 } 00297 00298 /** Attach a callback object/method 00299 * 00300 * @code 00301 * 00302 * class Bar { 00303 * public: 00304 * void myCallback( void ) { led1 = 1; } 00305 * }; 00306 * 00307 * DigitalOut led1( LED1 ); 00308 * PinDetect pin( p30 ); 00309 * Bar bar; 00310 * 00311 * main() { 00312 * pin.attach_asserted( &bar, &Bar::myCallback ); 00313 * } 00314 * 00315 * @endcode 00316 * 00317 * Call this function when a pin is asserted. 00318 * @param object An object that conatins the callback method. 00319 * @param method The method within the object to call. 00320 */ 00321 template<typename T> 00322 void attach_asserted(T *object, void (T::*member)(void)) { 00323 _callbackAsserted.attach( object, member ); 00324 } 00325 00326 /** Attach a callback function 00327 * 00328 * @code 00329 * 00330 * DigitalOut led1( LED1 ); 00331 * PinDetect pin( p30 ); 00332 * 00333 * void myCallback( void ) { 00334 * led1 = 0; 00335 * }; 00336 * 00337 * main() { 00338 * pin.attach_deasserted( &myCallback ); 00339 * } 00340 * 00341 * @endcode 00342 * 00343 * Call this function when a pin is deasserted. 00344 * @param function A C function pointer 00345 */ 00346 void attach_deasserted(void (*function)(void)) { 00347 _callbackDeasserted.attach( function ); 00348 } 00349 00350 /** Attach a callback object/method 00351 * 00352 * @code 00353 * 00354 * class Bar { 00355 * public: 00356 * void myCallback( void ) { led1 = 0; } 00357 * }; 00358 * 00359 * DigitalOut led1( LED1 ); 00360 * PinDetect pin( p30 ); 00361 * Bar bar; 00362 * 00363 * main() { 00364 * pin.attach_deasserted( &bar, &Bar::myCallback ); 00365 * } 00366 * 00367 * @endcode 00368 * 00369 * Call this function when a pin is deasserted. 00370 * @param object An object that conatins the callback method. 00371 * @param method The method within the object to call. 00372 */ 00373 template<typename T> 00374 void attach_deasserted(T *object, void (T::*member)(void)) { 00375 _callbackDeasserted.attach( object, member ); 00376 } 00377 00378 /** Attach a callback function 00379 * 00380 * @code 00381 * 00382 * DigitalOut led2( LED2 ); 00383 * PinDetect pin( p30 ); 00384 * 00385 * void myCallback( void ) { 00386 * led2 = 1; 00387 * }; 00388 * 00389 * main() { 00390 * pin.attach_asserted_held( &myCallback ); 00391 * } 00392 * 00393 * @endcode 00394 * 00395 * Call this function when a pin is asserted and held. 00396 * @param function A C function pointer 00397 */ 00398 void attach_asserted_held(void (*function)(void)) { 00399 _callbackAssertedHeld.attach( function ); 00400 } 00401 00402 /** Attach a callback object/method 00403 * 00404 * @code 00405 * 00406 * class Bar { 00407 * public: 00408 * void myCallback( void ) { led2 = 0; } 00409 * }; 00410 * 00411 * DigitalOut led2( LED2 ); 00412 * PinDetect pin( p30 ); 00413 * Bar bar; 00414 * 00415 * main() { 00416 * pin.attach_asserted_held( &bar, &Bar::myCallback ); 00417 * } 00418 * 00419 * @endcode 00420 * 00421 * Call this function when a pin is asserted and held. 00422 * @param object An object that conatins the callback method. 00423 * @param method The method within the object to call. 00424 */ 00425 template<typename T> 00426 void attach_asserted_held(T *object, void (T::*member)(void)) { 00427 _callbackAssertedHeld.attach( object, member ); 00428 } 00429 00430 /** Attach a callback function 00431 * 00432 * @code 00433 * 00434 * DigitalOut led3( LED3 ); 00435 * PinDetect pin( p30 ); 00436 * 00437 * void myCallback( void ) { 00438 * led3 = 1; 00439 * }; 00440 * 00441 * main() { 00442 * pin.attach_deasserted_held( &myCallback ); 00443 * } 00444 * 00445 * @endcode 00446 * 00447 * Call this function when a pin is deasserted and held. 00448 * @param function A C function pointer 00449 */ 00450 void attach_deasserted_held(void (*function)(void)) { 00451 _callbackDeassertedHeld.attach( function ); 00452 } 00453 00454 /** Attach a callback object/method 00455 * 00456 * @code 00457 * 00458 * class Bar { 00459 * public: 00460 * void myCallback( void ) { led3 = 0; } 00461 * }; 00462 * 00463 * DigitalOut led3( LED3 ); 00464 * PinDetect pin( p30 ); 00465 * Bar bar; 00466 * 00467 * main() { 00468 * pin.attach_deasserted_held( &bar, &Bar::myCallback ); 00469 * } 00470 * 00471 * @endcode 00472 * 00473 * Call this function when a pin is deasserted and held. 00474 * @param object An object that conatins the callback method. 00475 * @param method The method within the object to call. 00476 */ 00477 template<typename T> 00478 void attach_deasserted_held(T *object, void (T::*member)(void)) { 00479 _callbackDeassertedHeld.attach( object, member ); 00480 } 00481 00482 /** operator int() 00483 * 00484 * Read the value of the pin being sampled. 00485 */ 00486 operator int() { return _in->read(); } 00487 00488 protected: 00489 /** The Ticker periodic callback function 00490 */ 00491 void isr(void) { 00492 int currentState = _in->read(); 00493 00494 if ( currentState != _prevState ) { 00495 if ( _samplesTillAssert == 0 ) { 00496 _prevState = currentState; 00497 _samplesTillHeld = _samplesTillHeldReload; 00498 if ( currentState == _assertValue ) 00499 _callbackAsserted.call(); 00500 else 00501 _callbackDeasserted.call(); 00502 } 00503 else { 00504 _samplesTillAssert--; 00505 } 00506 } 00507 else { 00508 _samplesTillAssert = _samplesTillAssertReload; 00509 } 00510 00511 if ( _samplesTillHeld ) { 00512 if ( _prevState == currentState ) { 00513 _samplesTillHeld--; 00514 if ( _samplesTillHeld == 0 ) { 00515 if ( currentState == _assertValue ) 00516 _callbackAssertedHeld.call(); 00517 else 00518 _callbackDeassertedHeld.call(); 00519 } 00520 } 00521 else { 00522 _samplesTillHeld = 0; 00523 } 00524 } 00525 } 00526 00527 }; 00528 00529 }; // namespace AjK ends. 00530 00531 using namespace AjK; 00532 00533 #endif 00534
Generated on Sat Jul 16 2022 02:09:56 by
1.7.2