PinDetect rework, removed the continuous sampling, using just irq, timers and pin state sequence.
Fork of PinDetect by
PinDetectMod.h
00001 /* PinDetectMod 00002 * Copyright (c) 2015 Giuliano Dianda 00003 * Released under the MIT License: http://mbed.org/license/mit 00004 * 00005 * Rework of: PinDetect by Andy Kirkham 00006 */ 00007 00008 /* 00009 Copyright (c) 2010 Andy Kirkham 00010 00011 Permission is hereby granted, free of charge, to any person obtaining a copy 00012 of this software and associated documentation files (the "Software"), to deal 00013 in the Software without restriction, including without limitation the rights 00014 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00015 copies of the Software, and to permit persons to whom the Software is 00016 furnished to do so, subject to the following conditions: 00017 00018 The above copyright notice and this permission notice shall be included in 00019 all copies or substantial portions of the Software. 00020 00021 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00022 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00023 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00024 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00025 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00026 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00027 THE SOFTWARE. 00028 */ 00029 00030 #ifndef PIN_DETECT_MOD_H 00031 #define PIN_DETECT_MOD_H 00032 00033 #ifndef MBED_H 00034 #include "mbed.h" 00035 #endif 00036 00037 #ifndef PINDETECT_PINSTATES 00038 #define PINDETECT_PINSTATES 00039 00040 // pin state bitmask 00041 #define S_IDLE 0 00042 #define S_RINGING ((uint32_t)1<<0) 00043 #define S_ASSERTED ((uint32_t)1<<1) 00044 #define S_HELD ((uint32_t)1<<2) 00045 00046 #endif 00047 00048 /** PinDetectMod is a rework of PinDetect, . 00049 * 00050 * Unlike the original PinDetect which samples pin at specified rate, here is all about interrupts and timers, 00051 * because for some application the continuous sampling of a mostly idle pin is an overhead. 00052 * Pin state is evaluated in sequence deasserted->ringing->asserted->(->held_asserted)->ringing->deasserted 00053 * callback function can be attached to these state changes: 00054 * deasserted->asserted (e.g. as soon as button is pressed) 00055 * asserted->deasserted (e.g quick button pulse) 00056 * asserted->held_asserted (e.g. as soon as the button is evaluated to be held) 00057 * held_asserted->deasserted (e.g. long button pulse) 00058 * 00059 * Only callbacks that have been attached will be called by the library. 00060 * 00061 * Example: 00062 * @code 00063 * #include "mbed.h" 00064 * #include "PinDetectMod.h" 00065 * 00066 * DigitalOut led1( LED1 ); 00067 * PinDetect pin(p30, PullUp, 0); 00068 * 00069 * void keyPressed( void ) { 00070 * backligh_on(); 00071 * } 00072 * 00073 * void keyQuickPulsed( void ) { 00074 * increasevalue(); 00075 * } 00076 * 00077 * void keyPressedHeld( void ) { 00078 * beep(); 00079 * } 00080 * 00081 * void keyLongPulsed( void ) { 00082 * setup_menu(); 00083 * } 00084 * 00085 * int main() { 00086 * 00087 * pin.attach_asserted( &keyPressed ); 00088 * pin.attach_deasserted( &keyQuickPulsed ); 00089 * pin.attach_asserted_held( &keyPressedHeld ); 00090 * pin.attach_deasserted_held( &keyLongPulsed ); 00091 * 00092 * 00093 * while( 1 ) { 00094 * led1 = !led1; 00095 * wait( 0.2 ); 00096 * } 00097 * } 00098 * @endcode 00099 * 00100 */ 00101 class PinDetect { 00102 00103 00104 00105 public: 00106 00107 /** PinDetect constructor 00108 * 00109 * @see http://mbed.org/handbook/DigitalIn 00110 * @param p PinName is a valid pin that supports DigitalIn 00111 * @param m PinMode (PullUp, PullDown, PullNone....) 00112 * @param assertvalue pin state to be considered as asserted (0 or 1) 00113 * @param debounce_us debounce time in microseconds, default 5000 00114 * @param held_us time in microseconds for the state to be considered held_asserted, default 2000000 00115 */ 00116 PinDetect(PinName p, PinMode m, int assertvalue, unsigned int debounce_us=5000, unsigned int held_us=2000000): interr(p), _assertvalue(assertvalue) 00117 { 00118 debouncetime=debounce_us; 00119 heldtime=held_us; 00120 bouncein=0; 00121 bounceout=0; 00122 disable(); 00123 if (_assertvalue) { // pulse up 00124 interr.rise(this, &PinDetect::startpulse); // first rise then fall 00125 interr.fall(this, &PinDetect::endpulse); 00126 00127 } else { // pulse down 00128 interr.fall(this, &PinDetect::startpulse); // first fall then rise 00129 interr.rise(this, &PinDetect::endpulse); 00130 } 00131 interr.mode(m); 00132 statereset(); // pinstate=S_IDLE; 00133 trig=false; 00134 enable(); 00135 } 00136 00137 /** PinDetect destructor 00138 */ 00139 ~PinDetect() { 00140 interr.disable_irq(); 00141 timeoutbounce.detach(); 00142 timeoutheld.detach(); 00143 } 00144 /** Disable 00145 */ 00146 void disable() 00147 { 00148 interr.disable_irq(); 00149 statereset(); 00150 } 00151 /** Enable 00152 */ 00153 void enable() 00154 { 00155 interr.enable_irq(); 00156 statereset(); 00157 } 00158 00159 /** Set debounce time 00160 * 00161 * @param dbtime microseconds 00162 */ 00163 void setDebounceTime(unsigned int dbtime) { debouncetime = dbtime; } 00164 00165 /** Set time until held assumed. 00166 * 00167 * @param htime microseconds 00168 */ 00169 void setHeldTime(unsigned int htime) { heldtime = htime; } 00170 00171 00172 /** Attach a callback function 00173 * 00174 * @code 00175 * 00176 * DigitalOut led1( LED1 ); 00177 * PinDetect pin(p30, PullUp, 0); 00178 * 00179 * void myCallback( void ) { 00180 * led1 = 1; 00181 * }; 00182 * 00183 * main() { 00184 * pin.attach_asserted( &myCallback ); 00185 * } 00186 * 00187 * @endcode 00188 * 00189 * Call this function when a pin is asserted. 00190 * @param function A C function pointer 00191 */ 00192 void attach_asserted(void (*function)(void)) { 00193 callbackAsserted.attach( function ); 00194 } 00195 00196 /** Attach a callback object/method 00197 * 00198 * @code 00199 * 00200 * class Bar { 00201 * public: 00202 * void myCallback( void ) { led1 = 1; } 00203 * }; 00204 * 00205 * DigitalOut led1( LED1 ); 00206 * PinDetect pin(p30, PullUp, 0); 00207 * Bar bar; 00208 * 00209 * main() { 00210 * pin.attach_asserted( &bar, &Bar::myCallback ); 00211 * } 00212 * 00213 * @endcode 00214 * 00215 * Call this function when a pin is asserted. 00216 * @param object An object that conatins the callback method. 00217 * @param method The method within the object to call. 00218 */ 00219 template<typename T> 00220 void attach_asserted(T *object, void (T::*member)(void)) { 00221 callbackAsserted.attach( object, member ); 00222 } 00223 00224 /** Attach a callback function 00225 * 00226 * @code 00227 * 00228 * DigitalOut led1( LED1 ); 00229 * PinDetect pin(p30, PullUp, 0); 00230 * 00231 * void myCallback( void ) { 00232 * led1 = 0; 00233 * }; 00234 * 00235 * main() { 00236 * pin.attach_deasserted( &myCallback ); 00237 * } 00238 * 00239 * @endcode 00240 * 00241 * Call this function when a pin is deasserted (short pulse). 00242 * @param function A C function pointer 00243 */ 00244 void attach_deasserted(void (*function)(void)) { 00245 callbackDeasserted.attach( function ); 00246 } 00247 00248 /** Attach a callback object/method 00249 * 00250 * @code 00251 * 00252 * class Bar { 00253 * public: 00254 * void myCallback( void ) { led1 = 0; } 00255 * }; 00256 * 00257 * DigitalOut led1( LED1 ); 00258 * PinDetect pin(p30, PullUp, 0); 00259 * Bar bar; 00260 * 00261 * main() { 00262 * pin.attach_deasserted( &bar, &Bar::myCallback ); 00263 * } 00264 * 00265 * @endcode 00266 * 00267 * Call this function when a pin is deasserted (short pulse). 00268 * @param object An object that conatins the callback method. 00269 * @param method The method within the object to call. 00270 */ 00271 template<typename T> 00272 void attach_deasserted(T *object, void (T::*member)(void)) { 00273 callbackDeasserted.attach( object, member ); 00274 } 00275 00276 /** Attach a callback function 00277 * 00278 * @code 00279 * 00280 * DigitalOut led2( LED2 ); 00281 * PinDetect pin(p30, PullUp, 0); 00282 * 00283 * void myCallback( void ) { 00284 * led2 = 1; 00285 * }; 00286 * 00287 * main() { 00288 * pin.attach_asserted_held( &myCallback ); 00289 * } 00290 * 00291 * @endcode 00292 * 00293 * Call this function when a pin is asserted and held. 00294 * @param function A C function pointer 00295 */ 00296 void attach_asserted_held(void (*function)(void)) { 00297 callbackAssertedHeld.attach( function ); 00298 } 00299 00300 /** Attach a callback object/method 00301 * 00302 * @code 00303 * 00304 * class Bar { 00305 * public: 00306 * void myCallback( void ) { led2 = 0; } 00307 * }; 00308 * 00309 * DigitalOut led2( LED2 ); 00310 * PinDetect pin(p30, PullUp, 0); 00311 * Bar bar; 00312 * 00313 * main() { 00314 * pin.attach_asserted_held( &bar, &Bar::myCallback ); 00315 * } 00316 * 00317 * @endcode 00318 * 00319 * Call this function when a pin is asserted and held. 00320 * @param object An object that conatins the callback method. 00321 * @param method The method within the object to call. 00322 */ 00323 template<typename T> 00324 void attach_asserted_held(T *object, void (T::*member)(void)) { 00325 callbackAssertedHeld.attach( object, member ); 00326 } 00327 00328 /** Attach a callback function 00329 * 00330 * @code 00331 * 00332 * DigitalOut led3( LED3 ); 00333 * PinDetect pin(p30, PullUp, 0); 00334 * 00335 * void myCallback( void ) { 00336 * led3 = 1; 00337 * }; 00338 * 00339 * main() { 00340 * pin.attach_deasserted_held( &myCallback ); 00341 * } 00342 * 00343 * @endcode 00344 * 00345 * Call this function when a pin is deasserted after being held. 00346 * @param function A C function pointer 00347 */ 00348 void attach_deasserted_held(void (*function)(void)) { 00349 callbackDeassertedHeld.attach( function ); 00350 } 00351 00352 /** Attach a callback object/method 00353 * 00354 * @code 00355 * 00356 * class Bar { 00357 * public: 00358 * void myCallback( void ) { led3 = 0; } 00359 * }; 00360 * 00361 * DigitalOut led3( LED3 ); 00362 * PinDetect pin(p30, PullUp, 0); 00363 * Bar bar; 00364 * 00365 * main() { 00366 * pin.attach_deasserted_held( &bar, &Bar::myCallback ); 00367 * } 00368 * 00369 * @endcode 00370 * 00371 * Call this function when a pin is deasserted after being held. 00372 * @param object An object that conatins the callback method. 00373 * @param method The method within the object to call. 00374 */ 00375 template<typename T> 00376 void attach_deasserted_held(T *object, void (T::*member)(void)) { 00377 callbackDeassertedHeld.attach( object, member ); 00378 } 00379 00380 /** operator int() 00381 * 00382 * Read the value of the pin being sampled. 00383 */ 00384 operator int() { return interr.read(); } 00385 00386 /** Get the current pin state 00387 * 00388 * @return pinstate bitmask S_HELD|S_ASSERTED|S_RINGING, 0=S_IDLE 00389 */ 00390 unsigned int state() 00391 { 00392 return pinstate; 00393 } 00394 00395 /** Reset pinstate to S_IDLE and reset debounce/held timers 00396 */ 00397 void statereset() 00398 { 00399 pinstate=S_IDLE; 00400 timeoutheld.detach(); 00401 timeoutbounce.detach(); 00402 pinstate=S_IDLE; 00403 } 00404 /** Get the total bounces for deasserted->asserted 00405 * 00406 * @return bounces so far 00407 */ 00408 unsigned int getbouncein() 00409 { 00410 return bouncein; 00411 } 00412 /** Get the total bounces for asserted->deasserted 00413 * 00414 * @return bounces so far 00415 */ 00416 unsigned int getbounceout() 00417 { 00418 return bounceout; 00419 } 00420 00421 protected: 00422 00423 void startpulse() 00424 { 00425 pinstate|=S_RINGING; 00426 if((pinstate&S_ASSERTED)==0) timeoutbounce.attach_us(this, &PinDetect::onasserted, debouncetime); 00427 // else if state is asserted and we are here, it means we are debouncing transition to deasserted, timeout is already attached to ondeasserted() 00428 trig=true; // ISR completed 00429 } 00430 00431 void endpulse() 00432 { 00433 if(!trig) return; // first check if the previous startpulse ISR completed 00434 pinstate|=S_RINGING; 00435 00436 if((pinstate&S_ASSERTED)!=0) // if was asserted or held asserted, debounce transition to deasserted 00437 { 00438 timeoutheld.detach(); 00439 timeoutbounce.attach_us(this, &PinDetect::ondeasserted, debouncetime); 00440 } 00441 trig=false; 00442 } 00443 00444 void onasserted() 00445 { 00446 if(interr.read()!=_assertvalue) 00447 { 00448 bouncein++; 00449 return; // was a bounce 00450 } 00451 pinstate|=S_ASSERTED; // set asserted 00452 pinstate&= ~(S_RINGING|S_HELD); // clear ringing and held 00453 timeoutheld.attach_us(this, &PinDetect::onheld, heldtime); 00454 callbackAsserted.call(); // call function for pin state change (deasserted -> asserted) 00455 } 00456 00457 void onheld() 00458 { 00459 if((pinstate&S_RINGING)!=0 || (pinstate&S_ASSERTED)==0 || (interr.read()!=_assertvalue)) return; // to be valid, needs ringing=false asserted=true pinread=assertvalue 00460 pinstate|=S_HELD; // set held 00461 callbackAssertedHeld.call(); // call function for pin state change (asserted -> held asserted) 00462 } 00463 00464 void ondeasserted() 00465 { 00466 if((pinstate&(S_ASSERTED))==0) return; // pinstate was reset externally 00467 if(interr.read()==_assertvalue) 00468 { 00469 bounceout++; 00470 return; // was a bounce 00471 } 00472 if((pinstate&S_HELD)==0) callbackDeasserted.call(); // call function for pin state change (asserted -> deasserted)(quick pulse) 00473 else callbackDeassertedHeld.call(); // call function for pin state change (held asserted -> deasserted)(long pulse) 00474 pinstate=S_IDLE; 00475 } 00476 00477 private: 00478 InterruptIn interr; 00479 Timeout timeoutbounce; 00480 Timeout timeoutheld; 00481 unsigned int debouncetime; 00482 unsigned int heldtime; 00483 int _assertvalue; 00484 FunctionPointer callbackAsserted; 00485 FunctionPointer callbackDeasserted; 00486 FunctionPointer callbackAssertedHeld; 00487 FunctionPointer callbackDeassertedHeld; 00488 volatile unsigned int pinstate; 00489 volatile unsigned int bouncein; 00490 volatile unsigned int bounceout; 00491 00492 bool trig; 00493 00494 }; 00495 00496 00497 #endif
Generated on Wed Jul 13 2022 10:41:18 by
![doxygen](doxygen.png)