PinDetect rework, removed the continuous sampling, using just irq, timers and pin state sequence.
Fork of PinDetect by
Diff: PinDetect.h
- Revision:
- 4:3aca44118b7a
- Parent:
- 3:5ff38909c179
--- 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