Changed default PinMode from PullDown to PullDefault for compatibility with KL25Z

Dependents:   ChordJoy idd_hw2_andrewhead_chordjoy idd_hw2_kevinlee_typinglove idd_hw2_kevinlee_typinglove ... more

Fork of PinDetect by Andy K

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PinDetect.h Source File

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