Jorge Rodolfo Muñoz / PinDetect_for_KL25Z

Dependents:   Programa_juego_info

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     
00005     Copyright (c) 2010 Andy Kirkham
00006  
00007     Permission is hereby granted, free of charge, to any person obtaining a copy
00008     of this software and associated documentation files (the "Software"), to deal
00009     in the Software without restriction, including without limitation the rights
00010     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011     copies of the Software, and to permit persons to whom the Software is
00012     furnished to do so, subject to the following conditions:
00013  
00014     The above copyright notice and this permission notice shall be included in
00015     all copies or substantial portions of the Software.
00016  
00017     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00020     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00022     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00023     THE SOFTWARE.
00024 */
00025 
00026 #ifndef AJK_PIN_DETECT_H
00027 #define AJK_PIN_DETECT_H
00028 
00029 #ifndef MBED_H
00030 #include "mbed.h"
00031 #endif
00032 
00033 #ifndef PINDETECT_PIN_ASSTERED
00034 #define PINDETECT_PIN_ASSTERED   1
00035 #endif
00036 
00037 #ifndef PINDETECT_SAMPLE_PERIOD
00038 #define PINDETECT_SAMPLE_PERIOD 20000
00039 #endif
00040 
00041 #ifndef PINDETECT_ASSERT_COUNT  
00042 #define PINDETECT_ASSERT_COUNT  1
00043 #endif
00044 
00045 #ifndef PINDETECT_HOLD_COUNT
00046 #define PINDETECT_HOLD_COUNT    50
00047 #endif
00048 
00049 namespace AjK {
00050 
00051 /** PinDetect adds mechanical switch debouncing to DigitialIn and interrupt callbacks.
00052  *
00053  * This is done by sampling the specified pin at regular intervals and detecting any
00054  * change of state ( 0 -> 1 or 1 -> 0 ). When a state change is detected the attached
00055  * callback handler is called. Additionally, if the pin stays in the same state after
00056  * a state change for a defined period of time, an extra callback is made allowing a
00057  * program to detect when a "key is pressed and held down" rather than a momentary
00058  * key/switch press.
00059  *
00060  * All parameters are customisable which include:-
00061  *  <ul>
00062  *  <li> The sampling frequency. </li>
00063  *  <li> The number of continuous samples until a state change is detected. </li> 
00064  *  <li> The number of continuous samples until a key is assumed held after a state change. </li>
00065  *  <li> The logic level which is assumed to be asserted (0volts or +volts). </li>
00066  *  </ul>
00067  *
00068  * Only callbacks that have been attached will be called by the library.
00069  *
00070  * Example:
00071  * @code
00072  * #include "mbed.h"
00073  * #include "PinDetect.h"
00074  *
00075  * PinDetect  pin( p30 );
00076  * DigitialOut led1( LED1 );
00077  * DigitialOut led2( LED2 );
00078  * DigitialOut led3( LED3 );
00079  * DigitialOut led4( LED4 );
00080  *
00081  * void keyPressed( void ) {
00082  *     led2 = 1;
00083  *     led3 = 0;
00084  *     led4 = 0;
00085  * }
00086  *
00087  * void keyReleased( void ) {
00088  *     led2 = 0;
00089  *     led3 = 0;
00090  *     led4 = 0;
00091  * }
00092  *
00093  * void keyPressedHeld( void ) {
00094  *     led3 = 1;
00095  * }
00096  *
00097  * void keyReleasedHeld( void ) {
00098  *     led4 = 1;
00099  * }
00100  *
00101  * int main() {
00102  *
00103  *     pin.mode( PullDown );
00104  *     pin.attach_asserted( &keyPressed );
00105  *     pin.attach_deasserted( &keyReleased );
00106  *     pin.attach_asserted_held( &keyPressedHeld );
00107  *     pin.attach_deasserted_held( &keyReleasedHeld );
00108  *
00109  *     // Sampling does not begin until you set a frequency.
00110  *     // The default is 20ms. If you want a different frequency
00111  *     // then pass the period in microseconds for example, for 10ms :-
00112  *     //     pin.setSampleFrequency( 10000 );
00113  *     //
00114  *     pin.setSampleFrequency(); // Defaults to 20ms.
00115  *
00116  *     while( 1 ) {
00117  *         led1 = !led1;
00118  *         wait( 0.2 );
00119  *     }
00120  * }
00121  * @endcode
00122  *
00123  * This example will flash led1 in a similar to a standard starting program.
00124  *
00125  * Applying a "1" (switch on) to pin 30 will switch on led2, removing the "1" to "0"
00126  * (switch off) led2 goes out. Holding the "switch" at one for one second will switch
00127  * on led3. An unasserted P30 (switched off) will, after one second illuminate led4
00128  * when the deasserted calledback is called.
00129  *
00130  * The above is a very basic introduction. For more details:-
00131  * @see example.h
00132  */
00133 class PinDetect {
00134 
00135 protected:
00136     DigitalIn   *_in;
00137     Ticker      *_ticker;
00138     int         _prevState;
00139     int         _currentStateCounter;
00140     int         _sampleTime;
00141     int         _assertValue;
00142     int         _samplesTillAssertReload;
00143     int         _samplesTillAssert;
00144     int         _samplesTillHeldReload;
00145     int         _samplesTillHeld;
00146     FunctionPointer _callbackAsserted;
00147     FunctionPointer _callbackDeasserted;
00148     FunctionPointer _callbackAssertedHeld;
00149     FunctionPointer _callbackDeassertedHeld;
00150     
00151     /** initialise class
00152      *
00153      * @param PinName p is a valid pin that supports DigitalIn
00154      * @param PinMode m The mode the DigitalIn should use.
00155      */
00156     void init(PinName p, PinMode m) {
00157         _sampleTime              = PINDETECT_SAMPLE_PERIOD;
00158         _samplesTillAssert       = PINDETECT_ASSERT_COUNT;
00159         _samplesTillHeld         = 0;
00160         _samplesTillAssertReload = PINDETECT_ASSERT_COUNT;
00161         _samplesTillHeldReload   = PINDETECT_HOLD_COUNT;
00162         _assertValue             = PINDETECT_PIN_ASSTERED;
00163         
00164         _in = new DigitalIn( p );
00165         _in->mode( m );        
00166         _prevState = _in->read();        
00167         _ticker = new Ticker;
00168     }
00169     
00170 public:
00171 
00172     friend class Ticker;
00173     
00174     PinDetect() { error("You must supply a PinName"); }
00175 
00176     /** PinDetect constructor
00177      *
00178      * By default the PinMode is set to PullDown.
00179      *
00180      * @see http://mbed.org/handbook/DigitalIn
00181      * @param p PinName is a valid pin that supports DigitalIn
00182      */    
00183     PinDetect(PinName p, PinMode m) {
00184         init( p, PullUp );
00185     }
00186 
00187     /** PinDetect constructor
00188      *
00189      * @see http://mbed.org/handbook/DigitalIn
00190      * @param PinName p is a valid pin that supports DigitalIn
00191      * @param PinMode m The mode the DigitalIn should use.
00192      */    
00193     PinDetect(PinName p) {
00194         init( p, PullUp );
00195     }
00196     
00197     /** PinDetect destructor
00198      */    
00199     ~PinDetect() {
00200         if ( _ticker )  delete( _ticker );
00201         if ( _in )      delete( _in );
00202     }
00203     
00204     /** Set the sampling time in microseconds.
00205      *
00206      * @param int The time between pin samples in microseconds.
00207      */
00208     void setSampleFrequency(int i = PINDETECT_SAMPLE_PERIOD) { 
00209         _sampleTime = i; 
00210         _prevState  = _in->read();        
00211         _ticker->attach_us( this, &PinDetect::isr, _sampleTime );
00212     }
00213     
00214     /** Set the value used as assert.
00215      *
00216      * Defaults to 1 (ie if pin == 1 then pin asserted).
00217      *
00218      * @param int New assert value (1 or 0)
00219      */
00220     void setAssertValue (int i = PINDETECT_PIN_ASSTERED) { _assertValue = i & 1; }
00221     
00222     /** Set the number of continuous samples until assert assumed.
00223      *
00224      * Defaults to 1 (1 * sample frequency).
00225      *
00226      * @param int The number of continuous samples until assert assumed.
00227      */    
00228     void setSamplesTillAssert(int i) { _samplesTillAssertReload = i; }
00229     
00230     /** Set the number of continuous samples until held assumed.
00231      *
00232      * Defaults to 50 * sample frequency.
00233      *
00234      * @param int The number of continuous samples until held assumed.
00235      */    
00236     void setSamplesTillHeld(int i) { _samplesTillHeldReload = i; }
00237     
00238     /** Set the pin mode.
00239      *
00240      * @see http://mbed.org/projects/libraries/api/mbed/trunk/DigitalInOut#DigitalInOut.mode
00241      * @param PinMode m The mode to pass on to the DigitalIn
00242      */
00243     void mode(PinMode m) { _in->mode( m ); }
00244     
00245     /** Attach a callback function 
00246      *
00247      * @code
00248      *
00249      * DigitalOut led1( LED1 );
00250      * PinDetect pin( p30 );
00251      *
00252      * void myCallback( void ) {
00253      *   led1 = 1;
00254      * };
00255      * 
00256      * main() {
00257      *     pin.attach_asserted( &myCallback );
00258      * }
00259      *
00260      * @endcode
00261      *
00262      * Call this function when a pin is asserted.
00263      * @param function A C function pointer
00264      */
00265     void attach_asserted(void (*function)(void)) {
00266         _callbackAsserted.attach( function );
00267     }
00268     
00269     /** Attach a callback object/method 
00270      *
00271      * @code
00272      *
00273      * class Bar {
00274      *   public:
00275      *     void myCallback( void ) { led1 = 1; }
00276      * };
00277      *
00278      * DigitalOut led1( LED1 );
00279      * PinDetect pin( p30 );
00280      * Bar bar;
00281      *
00282      * main() {
00283      *     pin.attach_asserted( &bar, &Bar::myCallback );
00284      * }
00285      *
00286      * @endcode
00287      *
00288      * Call this function when a pin is asserted.
00289      * @param object An object that conatins the callback method.
00290      * @param method The method within the object to call.
00291      */
00292     template<typename T>
00293     void attach_asserted(T *object, void (T::*member)(void)) {
00294         _callbackAsserted.attach( object, member );        
00295     }
00296     
00297     /** Attach a callback function 
00298      *
00299      * @code
00300      *
00301      * DigitalOut led1( LED1 );
00302      * PinDetect pin( p30 );
00303      *
00304      * void myCallback( void ) {
00305      *   led1 = 0;
00306      * };
00307      *
00308      * main() {
00309      *     pin.attach_deasserted( &myCallback );
00310      * }
00311      *
00312      * @endcode
00313      *
00314      * Call this function when a pin is deasserted.
00315      * @param function A C function pointer
00316      */
00317     void attach_deasserted(void (*function)(void)) {
00318         _callbackDeasserted.attach( function );
00319     }
00320     
00321     /** Attach a callback object/method
00322      *
00323      * @code
00324      *
00325      * class Bar {
00326      *   public:
00327      *     void myCallback( void ) { led1 = 0; }
00328      * };
00329      *
00330      * DigitalOut led1( LED1 );
00331      * PinDetect pin( p30 );
00332      * Bar bar;
00333      * 
00334      * main() {
00335      *     pin.attach_deasserted( &bar, &Bar::myCallback );
00336      * }
00337      *
00338      * @endcode
00339      *
00340      * Call this function when a pin is deasserted.
00341      * @param object An object that conatins the callback method.
00342      * @param method The method within the object to call.
00343      */
00344     template<typename T>
00345     void attach_deasserted(T *object, void (T::*member)(void)) {
00346         _callbackDeasserted.attach( object, member );        
00347     }
00348     
00349     /** Attach a callback function 
00350      *
00351      * @code
00352      *
00353      * DigitalOut led2( LED2 );
00354      * PinDetect pin( p30 );
00355      *
00356      * void myCallback( void ) {
00357      *   led2 = 1;
00358      * };
00359      *
00360      * main() {
00361      *     pin.attach_asserted_held( &myCallback );
00362      * }
00363      *
00364      * @endcode
00365      *
00366      * Call this function when a pin is asserted and held.
00367      * @param function A C function pointer
00368      */
00369     void attach_asserted_held(void (*function)(void)) {
00370         _callbackAssertedHeld.attach( function );
00371     }
00372     
00373     /** Attach a callback object/method
00374      *
00375      * @code
00376      *
00377      * class Bar {
00378      *   public:
00379      *     void myCallback( void ) { led2 = 0; }
00380      * };
00381      *
00382      * DigitalOut led2( LED2 );
00383      * PinDetect pin( p30 );
00384      * Bar bar;
00385      * 
00386      * main() {
00387      *     pin.attach_asserted_held( &bar, &Bar::myCallback );
00388      * }
00389      *
00390      * @endcode
00391      *
00392      * Call this function when a pin is asserted and held.
00393      * @param object An object that conatins the callback method.
00394      * @param method The method within the object to call.
00395      */
00396     template<typename T>
00397     void attach_asserted_held(T *object, void (T::*member)(void)) {
00398         _callbackAssertedHeld.attach( object, member );        
00399     }
00400     
00401     /** Attach a callback function 
00402      *
00403      * @code
00404      *
00405      * DigitalOut led3( LED3 );
00406      * PinDetect pin( p30 );
00407      *
00408      * void myCallback( void ) {
00409      *   led3 = 1;
00410      * };
00411      *
00412      * main() {
00413      *     pin.attach_deasserted_held( &myCallback );
00414      * }
00415      *
00416      * @endcode
00417      *
00418      * Call this function when a pin is deasserted and held.
00419      * @param function A C function pointer
00420      */
00421     void attach_deasserted_held(void (*function)(void)) {
00422         _callbackDeassertedHeld.attach( function );
00423     }
00424     
00425     /** Attach a callback object/method
00426      *
00427      * @code
00428      *
00429      * class Bar {
00430      *   public:
00431      *     void myCallback( void ) { led3 = 0; }
00432      * };
00433      *
00434      * DigitalOut led3( LED3 );
00435      * PinDetect pin( p30 );
00436      * Bar bar;
00437      * 
00438      * main() {
00439      *     pin.attach_deasserted_held( &bar, &Bar::myCallback );
00440      * }
00441      *
00442      * @endcode
00443      *
00444      * Call this function when a pin is deasserted and held.
00445      * @param object An object that conatins the callback method.
00446      * @param method The method within the object to call.
00447      */
00448     template<typename T>
00449     void attach_deasserted_held(T *object, void (T::*member)(void)) {
00450         _callbackDeassertedHeld.attach( object, member );        
00451     }
00452     
00453     /** operator int()
00454      *
00455      * Read the value of the pin being sampled.
00456      */
00457     operator int() { return _in->read(); }
00458 
00459 protected:    
00460     /** The Ticker periodic callback function
00461      */
00462     void isr(void) {
00463         int currentState = _in->read();
00464     
00465         if ( currentState != _prevState ) {
00466             if ( _samplesTillAssert == 0 ) {
00467                 _prevState = currentState;
00468                 _samplesTillHeld = _samplesTillHeldReload;
00469                 if ( currentState == _assertValue ) 
00470                     _callbackAsserted.call();
00471                 else                              
00472                     _callbackDeasserted.call();
00473             }
00474             else {
00475                 _samplesTillAssert--;
00476             }
00477         }
00478         else {
00479             _samplesTillAssert = _samplesTillAssertReload;
00480         }
00481         
00482         if ( _samplesTillHeld ) {
00483             if ( _prevState == currentState ) {
00484                 _samplesTillHeld--;
00485                 if ( _samplesTillHeld == 0 ) {
00486                     if ( currentState == _assertValue ) 
00487                         _callbackAssertedHeld.call();
00488                     else                              
00489                         _callbackDeassertedHeld.call();
00490                 }
00491             }
00492             else {
00493                 _samplesTillHeld = 0;
00494             }
00495         }
00496     }
00497     
00498 };
00499 
00500 }; // namespace AjK ends.
00501 
00502 using namespace AjK;
00503 
00504 #endif