PinDetect rework, removed the continuous sampling, using just irq, timers and pin state sequence.
Fork of PinDetect by
Revision 4:3aca44118b7a, committed 2015-06-12
- Comitter:
- Geremia
- Date:
- Fri Jun 12 01:13:07 2015 +0000
- Parent:
- 3:5ff38909c179
- Commit message:
- revised comments
Changed in this revision
diff -r 5ff38909c179 -r 3aca44118b7a ChangeLog.h --- a/ChangeLog.h Wed May 06 21:29:16 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - 1.5 13 Jan 2011 - Made the isr() protected and made the class a friend of Ticker. - Read the previous state and store when the sample frequency is - set so that initial assert_deassert_held() isn't called at startup. - - 1.4 13 Jan 2011 - Added an extra overloaded constructor that allows - the DigitalIn PinMode to be passed when the the class - is declared. So mode() isn't really needed but is left - in for completeness. - - 1.3 13 Jan 2011 - Updated some doxygen comments. - - 1.2 13 Jan 2011 - Added ChangeLog.h file. - - 1.1 13 Jan 2011 - Fixed some typos. - - 1.0 13 Jan 2011 - Initial release. - -*/
diff -r 5ff38909c179 -r 3aca44118b7a PinDetect.h --- a/PinDetect.h Wed May 06 21:29:16 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,525 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef AJK_PIN_DETECT_H -#define AJK_PIN_DETECT_H - -#ifndef MBED_H -#include "mbed.h" -#endif - -#ifndef PINDETECT_PIN_ASSTERED -#define PINDETECT_PIN_ASSTERED 1 -#endif - -#ifndef PINDETECT_SAMPLE_PERIOD -#define PINDETECT_SAMPLE_PERIOD 20000 -#endif - -#ifndef PINDETECT_ASSERT_COUNT -#define PINDETECT_ASSERT_COUNT 1 -#endif - -#ifndef PINDETECT_PINSTATES -#define PINDETECT_PINSTATES - -// pin state bitmask -#define S_IDLE 0 -#define S_RINGING ((uint32_t)1<<0) -#define S_ASSERTED ((uint32_t)1<<1) -#define S_HELD ((uint32_t)1<<2) - - -#endif - -/** PinDetect adds mechanical switch debouncing to DigitialIn and interrupt callbacks. - * - * This is done by sampling the specified pin at regular intervals and detecting any - * change of state ( 0 -> 1 or 1 -> 0 ). When a state change is detected the attached - * callback handler is called. Additionally, if the pin stays in the same state after - * a state change for a defined period of time, an extra callback is made allowing a - * program to detect when a "key is pressed and held down" rather than a momentary - * key/switch press. - * - * All parameters are customisable which include:- - * <ul> - * <li> The sampling frequency. </li> - * <li> The number of continuous samples until a state change is detected. </li> - * <li> The number of continuous samples until a key is assumed held after a state change. </li> - * <li> The logic level which is assumed to be asserted (0volts or +volts). </li> - * </ul> - * - * Only callbacks that have been attached will be called by the library. - * - * Example: - * @code - * #include "mbed.h" - * #include "PinDetect.h" - * - * PinDetect pin( p30 ); - * DigitialOut led1( LED1 ); - * DigitialOut led2( LED2 ); - * DigitialOut led3( LED3 ); - * DigitialOut led4( LED4 ); - * - * void keyPressed( void ) { - * led2 = 1; - * led3 = 0; - * led4 = 0; - * } - * - * void keyReleased( void ) { - * led2 = 0; - * led3 = 0; - * led4 = 0; - * } - * - * void keyPressedHeld( void ) { - * led3 = 1; - * } - * - * void keyReleasedHeld( void ) { - * led4 = 1; - * } - * - * int main() { - * - * pin.mode( PullDown ); - * pin.attach_asserted( &keyPressed ); - * pin.attach_deasserted( &keyReleased ); - * pin.attach_asserted_held( &keyPressedHeld ); - * pin.attach_deasserted_held( &keyReleasedHeld ); - * - * // Sampling does not begin until you set a frequency. - * // The default is 20ms. If you want a different frequency - * // then pass the period in microseconds for example, for 10ms :- - * // pin.setSampleFrequency( 10000 ); - * // - * pin.setSampleFrequency(); // Defaults to 20ms. - * - * while( 1 ) { - * led1 = !led1; - * wait( 0.2 ); - * } - * } - * @endcode - * - * This example will flash led1 in a similar to a standard starting program. - * - * Applying a "1" (switch on) to pin 30 will switch on led2, removing the "1" to "0" - * (switch off) led2 goes out. Holding the "switch" at one for one second will switch - * on led3. An unasserted P30 (switched off) will, after one second illuminate led4 - * when the deasserted calledback is called. - * - * The above is a very basic introduction. For more details:- - * @see example.h - */ -class PinDetect { - - - -public: - - /** PinDetect constructor - * - * By default the PinMode is set to PullDown. - * - * @see http://mbed.org/handbook/DigitalIn - * @param p PinName is a valid pin that supports DigitalIn - */ - PinDetect(PinName p, PinMode m, int assertvalue, unsigned int debounce_us, unsigned int held_us): interr(p), _assertvalue(assertvalue) - { - debouncetime=debounce_us; - heldtime=held_us; - bouncein=0; - bounceout=0; - disable(); - if (_assertvalue) { // pulse up - interr.rise(this, &PinDetect::startpulse); // first rise then fall - interr.fall(this, &PinDetect::endpulse); - - } else { // pulse down - interr.fall(this, &PinDetect::startpulse); // first fall then rise - interr.rise(this, &PinDetect::endpulse); - } - interr.mode(m); - statereset(); // pinstate=S_IDLE; - trig=false; - enable(); - } - - /** PinDetect destructor - */ - ~PinDetect() { - interr.disable_irq(); - timeoutbounce.detach(); - timeoutheld.detach(); - } - - void disable() - { - interr.disable_irq(); - statereset(); - } - void enable() - { - interr.enable_irq(); - statereset(); - } - - /** Set the number of continuous samples until assert assumed. - * - * Defaults to 1 (1 * sample frequency). - * - * @param int The number of continuous samples until assert assumed. - */ - void setDebounceTime(int i) { debouncetime = i; } - - /** Set the number of continuous samples until held assumed. - * - * Defaults to 50 * sample frequency. - * - * @param int The number of continuous samples until held assumed. - */ - void setHeldTime(int i) { heldtime = i; } - - - /** Attach a callback function - * - * @code - * - * DigitalOut led1( LED1 ); - * PinDetect pin( p30 ); - * - * void myCallback( void ) { - * led1 = 1; - * }; - * - * main() { - * pin.attach_asserted( &myCallback ); - * } - * - * @endcode - * - * Call this function when a pin is asserted. - * @param function A C function pointer - */ - void attach_asserted(void (*function)(void)) { - callbackAsserted.attach( function ); - } - - /** Attach a callback object/method - * - * @code - * - * class Bar { - * public: - * void myCallback( void ) { led1 = 1; } - * }; - * - * DigitalOut led1( LED1 ); - * PinDetect pin( p30 ); - * Bar bar; - * - * main() { - * pin.attach_asserted( &bar, &Bar::myCallback ); - * } - * - * @endcode - * - * Call this function when a pin is asserted. - * @param object An object that conatins the callback method. - * @param method The method within the object to call. - */ - template<typename T> - void attach_asserted(T *object, void (T::*member)(void)) { - callbackAsserted.attach( object, member ); - } - - /** Attach a callback function - * - * @code - * - * DigitalOut led1( LED1 ); - * PinDetect pin( p30 ); - * - * void myCallback( void ) { - * led1 = 0; - * }; - * - * main() { - * pin.attach_deasserted( &myCallback ); - * } - * - * @endcode - * - * Call this function when a pin is deasserted. - * @param function A C function pointer - */ - void attach_deasserted(void (*function)(void)) { - callbackDeasserted.attach( function ); - } - - /** Attach a callback object/method - * - * @code - * - * class Bar { - * public: - * void myCallback( void ) { led1 = 0; } - * }; - * - * DigitalOut led1( LED1 ); - * PinDetect pin( p30 ); - * Bar bar; - * - * main() { - * pin.attach_deasserted( &bar, &Bar::myCallback ); - * } - * - * @endcode - * - * Call this function when a pin is deasserted. - * @param object An object that conatins the callback method. - * @param method The method within the object to call. - */ - template<typename T> - void attach_deasserted(T *object, void (T::*member)(void)) { - callbackDeasserted.attach( object, member ); - } - - /** Attach a callback function - * - * @code - * - * DigitalOut led2( LED2 ); - * PinDetect pin( p30 ); - * - * void myCallback( void ) { - * led2 = 1; - * }; - * - * main() { - * pin.attach_asserted_held( &myCallback ); - * } - * - * @endcode - * - * Call this function when a pin is asserted and held. - * @param function A C function pointer - */ - void attach_asserted_held(void (*function)(void)) { - callbackAssertedHeld.attach( function ); - } - - /** Attach a callback object/method - * - * @code - * - * class Bar { - * public: - * void myCallback( void ) { led2 = 0; } - * }; - * - * DigitalOut led2( LED2 ); - * PinDetect pin( p30 ); - * Bar bar; - * - * main() { - * pin.attach_asserted_held( &bar, &Bar::myCallback ); - * } - * - * @endcode - * - * Call this function when a pin is asserted and held. - * @param object An object that conatins the callback method. - * @param method The method within the object to call. - */ - template<typename T> - void attach_asserted_held(T *object, void (T::*member)(void)) { - callbackAssertedHeld.attach( object, member ); - } - - /** Attach a callback function - * - * @code - * - * DigitalOut led3( LED3 ); - * PinDetect pin( p30 ); - * - * void myCallback( void ) { - * led3 = 1; - * }; - * - * main() { - * pin.attach_deasserted_held( &myCallback ); - * } - * - * @endcode - * - * Call this function when a pin is deasserted and held. - * @param function A C function pointer - */ - void attach_deasserted_held(void (*function)(void)) { - callbackDeassertedHeld.attach( function ); - } - - /** Attach a callback object/method - * - * @code - * - * class Bar { - * public: - * void myCallback( void ) { led3 = 0; } - * }; - * - * DigitalOut led3( LED3 ); - * PinDetect pin( p30 ); - * Bar bar; - * - * main() { - * pin.attach_deasserted_held( &bar, &Bar::myCallback ); - * } - * - * @endcode - * - * Call this function when a pin is deasserted and held. - * @param object An object that conatins the callback method. - * @param method The method within the object to call. - */ - template<typename T> - void attach_deasserted_held(T *object, void (T::*member)(void)) { - callbackDeassertedHeld.attach( object, member ); - } - - /** operator int() - * - * Read the value of the pin being sampled. - */ - operator int() { return interr.read(); } - - /** Get the current pin state - * - * @return pinstate bitmask S_HELD|S_ASSERTED|S_RINGING, 0=S_IDLE - */ - unsigned int state() - { - return pinstate; - } - - /** Reset pinstate to S_IDLE and reset debounce/held timers - * - * @return pinstate bitmask S_HELD|S_ASSERTED|S_RINGING, 0=S_IDLE - */ - void statereset() - { - pinstate=S_IDLE; - timeoutheld.detach(); - timeoutbounce.detach(); - pinstate=S_IDLE; - } - unsigned int getbouncein() - { - return bouncein; - } - unsigned int getbounceout() - { - return bounceout; - } - -protected: - - void startpulse() - { - pinstate|=S_RINGING; - if((pinstate&S_ASSERTED)==0) timeoutbounce.attach_us(this, &PinDetect::onasserted, debouncetime); - // else if state is asserted and we are here, it means we are debouncing transition to deasserted, timeout is already attached to ondeasserted() - trig=true; // ISR completed - } - - void endpulse() - { - if(!trig) return; // first check if the previous startpulse ISR completed - pinstate|=S_RINGING; - - if((pinstate&S_ASSERTED)!=0) // if was asserted or held asserted, debounce transition to deasserted - { - timeoutheld.detach(); - timeoutbounce.attach_us(this, &PinDetect::ondeasserted, debouncetime); - } - trig=false; - } - - void onasserted() - { - if(interr.read()!=_assertvalue) - { - bouncein++; - return; // was a bounce - } - pinstate|=S_ASSERTED; // set asserted - pinstate&= ~(S_RINGING|S_HELD); // clear ringing and held - timeoutheld.attach_us(this, &PinDetect::onheld, heldtime); - callbackAsserted.call(); // call function for pin state change (deasserted -> asserted) - } - - void onheld() - { - if((pinstate&S_RINGING)!=0 || (pinstate&S_ASSERTED)==0 || (interr.read()!=_assertvalue)) return; // to be valid, needs ringing=false asserted=true pinread=assertvalue - pinstate|=S_HELD; // set held - callbackAssertedHeld.call(); // call function for pin state change (asserted -> held asserted) - } - - void ondeasserted() - { - if((pinstate&(S_ASSERTED))==0) return; // pinstate was reset externally - if(interr.read()==_assertvalue) - { - bounceout++; - return; // was a bounce - } - if((pinstate&S_HELD)==0) callbackDeasserted.call(); // call function for pin state change (asserted -> deasserted)(quick pulse) - else callbackDeassertedHeld.call(); // call function for pin state change (held asserted -> deasserted)(long pulse) - pinstate=S_IDLE; - } - -private: - InterruptIn interr; - Timeout timeoutbounce; - Timeout timeoutheld; - unsigned int debouncetime; - unsigned int heldtime; - int _assertvalue; - FunctionPointer callbackAsserted; - FunctionPointer callbackDeasserted; - FunctionPointer callbackAssertedHeld; - FunctionPointer callbackDeassertedHeld; - volatile unsigned int pinstate; - volatile unsigned int bouncein; - volatile unsigned int bounceout; - - bool trig; - -}; - - -#endif
diff -r 5ff38909c179 -r 3aca44118b7a PinDetectMod.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PinDetectMod.h Fri Jun 12 01:13:07 2015 +0000 @@ -0,0 +1,497 @@ + /* PinDetectMod + * Copyright (c) 2015 Giuliano Dianda + * Released under the MIT License: http://mbed.org/license/mit + * + * Rework of: PinDetect by Andy Kirkham + */ + +/* + Copyright (c) 2010 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef PIN_DETECT_MOD_H +#define PIN_DETECT_MOD_H + +#ifndef MBED_H +#include "mbed.h" +#endif + +#ifndef PINDETECT_PINSTATES +#define PINDETECT_PINSTATES + +// pin state bitmask +#define S_IDLE 0 +#define S_RINGING ((uint32_t)1<<0) +#define S_ASSERTED ((uint32_t)1<<1) +#define S_HELD ((uint32_t)1<<2) + +#endif + +/** PinDetectMod is a rework of PinDetect, . + * + * Unlike the original PinDetect which samples pin at specified rate, here is all about interrupts and timers, + * because for some application the continuous sampling of a mostly idle pin is an overhead. + * Pin state is evaluated in sequence deasserted->ringing->asserted->(->held_asserted)->ringing->deasserted + * callback function can be attached to these state changes: + * deasserted->asserted (e.g. as soon as button is pressed) + * asserted->deasserted (e.g quick button pulse) + * asserted->held_asserted (e.g. as soon as the button is evaluated to be held) + * held_asserted->deasserted (e.g. long button pulse) + * + * Only callbacks that have been attached will be called by the library. + * + * Example: + * @code + * #include "mbed.h" + * #include "PinDetectMod.h" + * + * DigitalOut led1( LED1 ); + * PinDetect pin(p30, PullUp, 0); + * + * void keyPressed( void ) { + * backligh_on(); + * } + * + * void keyQuickPulsed( void ) { + * increasevalue(); + * } + * + * void keyPressedHeld( void ) { + * beep(); + * } + * + * void keyLongPulsed( void ) { + * setup_menu(); + * } + * + * int main() { + * + * pin.attach_asserted( &keyPressed ); + * pin.attach_deasserted( &keyQuickPulsed ); + * pin.attach_asserted_held( &keyPressedHeld ); + * pin.attach_deasserted_held( &keyLongPulsed ); + * + * + * while( 1 ) { + * led1 = !led1; + * wait( 0.2 ); + * } + * } + * @endcode + * + */ +class PinDetect { + + + +public: + + /** PinDetect constructor + * + * @see http://mbed.org/handbook/DigitalIn + * @param p PinName is a valid pin that supports DigitalIn + * @param m PinMode (PullUp, PullDown, PullNone....) + * @param assertvalue pin state to be considered as asserted (0 or 1) + * @param debounce_us debounce time in microseconds, default 5000 + * @param held_us time in microseconds for the state to be considered held_asserted, default 2000000 + */ + PinDetect(PinName p, PinMode m, int assertvalue, unsigned int debounce_us=5000, unsigned int held_us=2000000): interr(p), _assertvalue(assertvalue) + { + debouncetime=debounce_us; + heldtime=held_us; + bouncein=0; + bounceout=0; + disable(); + if (_assertvalue) { // pulse up + interr.rise(this, &PinDetect::startpulse); // first rise then fall + interr.fall(this, &PinDetect::endpulse); + + } else { // pulse down + interr.fall(this, &PinDetect::startpulse); // first fall then rise + interr.rise(this, &PinDetect::endpulse); + } + interr.mode(m); + statereset(); // pinstate=S_IDLE; + trig=false; + enable(); + } + + /** PinDetect destructor + */ + ~PinDetect() { + interr.disable_irq(); + timeoutbounce.detach(); + timeoutheld.detach(); + } + /** Disable + */ + void disable() + { + interr.disable_irq(); + statereset(); + } + /** Enable + */ + void enable() + { + interr.enable_irq(); + statereset(); + } + + /** Set debounce time + * + * @param dbtime microseconds + */ + void setDebounceTime(unsigned int dbtime) { debouncetime = dbtime; } + + /** Set time until held assumed. + * + * @param htime microseconds + */ + void setHeldTime(unsigned int htime) { heldtime = htime; } + + + /** Attach a callback function + * + * @code + * + * DigitalOut led1( LED1 ); + * PinDetect pin(p30, PullUp, 0); + * + * void myCallback( void ) { + * led1 = 1; + * }; + * + * main() { + * pin.attach_asserted( &myCallback ); + * } + * + * @endcode + * + * Call this function when a pin is asserted. + * @param function A C function pointer + */ + void attach_asserted(void (*function)(void)) { + callbackAsserted.attach( function ); + } + + /** Attach a callback object/method + * + * @code + * + * class Bar { + * public: + * void myCallback( void ) { led1 = 1; } + * }; + * + * DigitalOut led1( LED1 ); + * PinDetect pin(p30, PullUp, 0); + * Bar bar; + * + * main() { + * pin.attach_asserted( &bar, &Bar::myCallback ); + * } + * + * @endcode + * + * Call this function when a pin is asserted. + * @param object An object that conatins the callback method. + * @param method The method within the object to call. + */ + template<typename T> + void attach_asserted(T *object, void (T::*member)(void)) { + callbackAsserted.attach( object, member ); + } + + /** Attach a callback function + * + * @code + * + * DigitalOut led1( LED1 ); + * PinDetect pin(p30, PullUp, 0); + * + * void myCallback( void ) { + * led1 = 0; + * }; + * + * main() { + * pin.attach_deasserted( &myCallback ); + * } + * + * @endcode + * + * Call this function when a pin is deasserted (short pulse). + * @param function A C function pointer + */ + void attach_deasserted(void (*function)(void)) { + callbackDeasserted.attach( function ); + } + + /** Attach a callback object/method + * + * @code + * + * class Bar { + * public: + * void myCallback( void ) { led1 = 0; } + * }; + * + * DigitalOut led1( LED1 ); + * PinDetect pin(p30, PullUp, 0); + * Bar bar; + * + * main() { + * pin.attach_deasserted( &bar, &Bar::myCallback ); + * } + * + * @endcode + * + * Call this function when a pin is deasserted (short pulse). + * @param object An object that conatins the callback method. + * @param method The method within the object to call. + */ + template<typename T> + void attach_deasserted(T *object, void (T::*member)(void)) { + callbackDeasserted.attach( object, member ); + } + + /** Attach a callback function + * + * @code + * + * DigitalOut led2( LED2 ); + * PinDetect pin(p30, PullUp, 0); + * + * void myCallback( void ) { + * led2 = 1; + * }; + * + * main() { + * pin.attach_asserted_held( &myCallback ); + * } + * + * @endcode + * + * Call this function when a pin is asserted and held. + * @param function A C function pointer + */ + void attach_asserted_held(void (*function)(void)) { + callbackAssertedHeld.attach( function ); + } + + /** Attach a callback object/method + * + * @code + * + * class Bar { + * public: + * void myCallback( void ) { led2 = 0; } + * }; + * + * DigitalOut led2( LED2 ); + * PinDetect pin(p30, PullUp, 0); + * Bar bar; + * + * main() { + * pin.attach_asserted_held( &bar, &Bar::myCallback ); + * } + * + * @endcode + * + * Call this function when a pin is asserted and held. + * @param object An object that conatins the callback method. + * @param method The method within the object to call. + */ + template<typename T> + void attach_asserted_held(T *object, void (T::*member)(void)) { + callbackAssertedHeld.attach( object, member ); + } + + /** Attach a callback function + * + * @code + * + * DigitalOut led3( LED3 ); + * PinDetect pin(p30, PullUp, 0); + * + * void myCallback( void ) { + * led3 = 1; + * }; + * + * main() { + * pin.attach_deasserted_held( &myCallback ); + * } + * + * @endcode + * + * Call this function when a pin is deasserted after being held. + * @param function A C function pointer + */ + void attach_deasserted_held(void (*function)(void)) { + callbackDeassertedHeld.attach( function ); + } + + /** Attach a callback object/method + * + * @code + * + * class Bar { + * public: + * void myCallback( void ) { led3 = 0; } + * }; + * + * DigitalOut led3( LED3 ); + * PinDetect pin(p30, PullUp, 0); + * Bar bar; + * + * main() { + * pin.attach_deasserted_held( &bar, &Bar::myCallback ); + * } + * + * @endcode + * + * Call this function when a pin is deasserted after being held. + * @param object An object that conatins the callback method. + * @param method The method within the object to call. + */ + template<typename T> + void attach_deasserted_held(T *object, void (T::*member)(void)) { + callbackDeassertedHeld.attach( object, member ); + } + + /** operator int() + * + * Read the value of the pin being sampled. + */ + operator int() { return interr.read(); } + + /** Get the current pin state + * + * @return pinstate bitmask S_HELD|S_ASSERTED|S_RINGING, 0=S_IDLE + */ + unsigned int state() + { + return pinstate; + } + + /** Reset pinstate to S_IDLE and reset debounce/held timers + */ + void statereset() + { + pinstate=S_IDLE; + timeoutheld.detach(); + timeoutbounce.detach(); + pinstate=S_IDLE; + } + /** Get the total bounces for deasserted->asserted + * + * @return bounces so far + */ + unsigned int getbouncein() + { + return bouncein; + } + /** Get the total bounces for asserted->deasserted + * + * @return bounces so far + */ + unsigned int getbounceout() + { + return bounceout; + } + +protected: + + void startpulse() + { + pinstate|=S_RINGING; + if((pinstate&S_ASSERTED)==0) timeoutbounce.attach_us(this, &PinDetect::onasserted, debouncetime); + // else if state is asserted and we are here, it means we are debouncing transition to deasserted, timeout is already attached to ondeasserted() + trig=true; // ISR completed + } + + void endpulse() + { + if(!trig) return; // first check if the previous startpulse ISR completed + pinstate|=S_RINGING; + + if((pinstate&S_ASSERTED)!=0) // if was asserted or held asserted, debounce transition to deasserted + { + timeoutheld.detach(); + timeoutbounce.attach_us(this, &PinDetect::ondeasserted, debouncetime); + } + trig=false; + } + + void onasserted() + { + if(interr.read()!=_assertvalue) + { + bouncein++; + return; // was a bounce + } + pinstate|=S_ASSERTED; // set asserted + pinstate&= ~(S_RINGING|S_HELD); // clear ringing and held + timeoutheld.attach_us(this, &PinDetect::onheld, heldtime); + callbackAsserted.call(); // call function for pin state change (deasserted -> asserted) + } + + void onheld() + { + if((pinstate&S_RINGING)!=0 || (pinstate&S_ASSERTED)==0 || (interr.read()!=_assertvalue)) return; // to be valid, needs ringing=false asserted=true pinread=assertvalue + pinstate|=S_HELD; // set held + callbackAssertedHeld.call(); // call function for pin state change (asserted -> held asserted) + } + + void ondeasserted() + { + if((pinstate&(S_ASSERTED))==0) return; // pinstate was reset externally + if(interr.read()==_assertvalue) + { + bounceout++; + return; // was a bounce + } + if((pinstate&S_HELD)==0) callbackDeasserted.call(); // call function for pin state change (asserted -> deasserted)(quick pulse) + else callbackDeassertedHeld.call(); // call function for pin state change (held asserted -> deasserted)(long pulse) + pinstate=S_IDLE; + } + +private: + InterruptIn interr; + Timeout timeoutbounce; + Timeout timeoutheld; + unsigned int debouncetime; + unsigned int heldtime; + int _assertvalue; + FunctionPointer callbackAsserted; + FunctionPointer callbackDeasserted; + FunctionPointer callbackAssertedHeld; + FunctionPointer callbackDeassertedHeld; + volatile unsigned int pinstate; + volatile unsigned int bouncein; + volatile unsigned int bounceout; + + bool trig; + +}; + + +#endif
diff -r 5ff38909c179 -r 3aca44118b7a example.h --- a/example.h Wed May 06 21:29:16 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - Copyright (c) 2010 Andy Kirkham - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifdef PINDETECT_EXAMPLE_COMPILE - -#include "mbed.h" -#include "PinDetect.h" - -PinDetect pin ( p21 ); -DigitalOut led1( LED1 ); -DigitalOut led2( LED2 ); -DigitalOut led3( LED3 ); -DigitalOut led4( LED4 ); - -/* - * Note, the PinDetect can be defined thus:- - * PinDetect pin( p21, PullDown ); - * This allows you to specify the DigitalIn pinmode - * when you create the PinDetect object. This means - * using pin.mode() later is then no longer required. - */ - -// C function callbacks follow. - -void keyPressed( void ) { - led2 = 1; - led3 = 0; - led4 = 0; -} - -void keyReleased( void ) { - led2 = 0; - led3 = 0; - led4 = 0; -} - -void keyPressedHeld( void ) { - led3 = 1; -} - -void keyReleasedHeld( void ) { - led4 = 1; -} - -// The main program. - -int main() { - - pin.mode( PullDown ); - pin.attach_asserted( &keyPressed ); - pin.attach_deasserted( &keyReleased ); - pin.attach_asserted_held( &keyPressedHeld ); - - // This callback will often be of little use as it's - // called after every assertion/deassertion. However, - // it's provided for completeness. You may find a use - // for it. If not, just don't attach a callback and it - // will not activate. - pin.attach_deasserted_held( &keyReleasedHeld ); - - // You can define how many continuous samples must be - // asserted before the attach_asserted() function is called. - // pin.setSamplesTillAssert( 10 ); - // This would mean 10 * 20ms debounce time = 200ms. - - // You can define how many continuous samples must be - // asserted before the attach_asserted_held() function is called. - // pin.setSamplesTillHeld( 200 ); - // This would mean 200 * 20ms debounce time = 2seconds. - - // By default, "asserted" assumes the pin going high from 0volts to 5volts - // and deasserted assumes going from 5volts to 0volts. You can invert this - // logic so that going to 0volts is asserted and going to 5volts is deasserted - // using this setup function:- - // pin.setAssertValue( 0 ); - - // Sampling does NOT begin until you set the frequency. So, until - // you call this function NO callbacks will be made. With no arguments - // passed the default is 20000 microseconds (20ms). Specifiy the sampling - // period in microseconds if you want a different value to 20ms. - // For example, for a sampling period of 10ms do:- - // pin.setSampleFrequency( 10000 ); - // Note, if you change the sampling frequency you will probably also - // want to change the number of samples till assert and held as show - // above. - pin.setSampleFrequency(); // Defaults to 20ms. - - while( 1 ) { - led1 = !led1; - wait( 0.2 ); - } -} - -#endif