PinDetect rework, removed the continuous sampling, using just irq, timers and pin state sequence.

Fork of PinDetect by Andy K

Committer:
Geremia
Date:
Wed May 06 21:29:16 2015 +0000
Revision:
3:5ff38909c179
Parent:
2:cb3afc45028b
dont remember

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AjK 0:4f4ccb203a70 1 /*
AjK 0:4f4ccb203a70 2 Copyright (c) 2010 Andy Kirkham
AjK 0:4f4ccb203a70 3
AjK 0:4f4ccb203a70 4 Permission is hereby granted, free of charge, to any person obtaining a copy
AjK 0:4f4ccb203a70 5 of this software and associated documentation files (the "Software"), to deal
AjK 0:4f4ccb203a70 6 in the Software without restriction, including without limitation the rights
AjK 0:4f4ccb203a70 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
AjK 0:4f4ccb203a70 8 copies of the Software, and to permit persons to whom the Software is
AjK 0:4f4ccb203a70 9 furnished to do so, subject to the following conditions:
AjK 0:4f4ccb203a70 10
AjK 0:4f4ccb203a70 11 The above copyright notice and this permission notice shall be included in
AjK 0:4f4ccb203a70 12 all copies or substantial portions of the Software.
AjK 0:4f4ccb203a70 13
AjK 0:4f4ccb203a70 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
AjK 0:4f4ccb203a70 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
AjK 0:4f4ccb203a70 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AjK 0:4f4ccb203a70 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
AjK 0:4f4ccb203a70 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AjK 0:4f4ccb203a70 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
AjK 0:4f4ccb203a70 20 THE SOFTWARE.
AjK 0:4f4ccb203a70 21 */
AjK 0:4f4ccb203a70 22
AjK 0:4f4ccb203a70 23 #ifndef AJK_PIN_DETECT_H
AjK 0:4f4ccb203a70 24 #define AJK_PIN_DETECT_H
AjK 0:4f4ccb203a70 25
AjK 0:4f4ccb203a70 26 #ifndef MBED_H
AjK 0:4f4ccb203a70 27 #include "mbed.h"
AjK 0:4f4ccb203a70 28 #endif
AjK 0:4f4ccb203a70 29
AjK 0:4f4ccb203a70 30 #ifndef PINDETECT_PIN_ASSTERED
AjK 0:4f4ccb203a70 31 #define PINDETECT_PIN_ASSTERED 1
AjK 0:4f4ccb203a70 32 #endif
AjK 0:4f4ccb203a70 33
AjK 0:4f4ccb203a70 34 #ifndef PINDETECT_SAMPLE_PERIOD
AjK 0:4f4ccb203a70 35 #define PINDETECT_SAMPLE_PERIOD 20000
AjK 0:4f4ccb203a70 36 #endif
AjK 0:4f4ccb203a70 37
AjK 0:4f4ccb203a70 38 #ifndef PINDETECT_ASSERT_COUNT
AjK 0:4f4ccb203a70 39 #define PINDETECT_ASSERT_COUNT 1
AjK 0:4f4ccb203a70 40 #endif
AjK 0:4f4ccb203a70 41
Geremia 3:5ff38909c179 42 #ifndef PINDETECT_PINSTATES
Geremia 3:5ff38909c179 43 #define PINDETECT_PINSTATES
Geremia 3:5ff38909c179 44
Geremia 3:5ff38909c179 45 // pin state bitmask
Geremia 3:5ff38909c179 46 #define S_IDLE 0
Geremia 3:5ff38909c179 47 #define S_RINGING ((uint32_t)1<<0)
Geremia 3:5ff38909c179 48 #define S_ASSERTED ((uint32_t)1<<1)
Geremia 3:5ff38909c179 49 #define S_HELD ((uint32_t)1<<2)
Geremia 3:5ff38909c179 50
Geremia 3:5ff38909c179 51
AjK 0:4f4ccb203a70 52 #endif
AjK 0:4f4ccb203a70 53
AjK 0:4f4ccb203a70 54 /** PinDetect adds mechanical switch debouncing to DigitialIn and interrupt callbacks.
AjK 0:4f4ccb203a70 55 *
AjK 0:4f4ccb203a70 56 * This is done by sampling the specified pin at regular intervals and detecting any
AjK 0:4f4ccb203a70 57 * change of state ( 0 -> 1 or 1 -> 0 ). When a state change is detected the attached
AjK 0:4f4ccb203a70 58 * callback handler is called. Additionally, if the pin stays in the same state after
AjK 0:4f4ccb203a70 59 * a state change for a defined period of time, an extra callback is made allowing a
AjK 0:4f4ccb203a70 60 * program to detect when a "key is pressed and held down" rather than a momentary
AjK 0:4f4ccb203a70 61 * key/switch press.
AjK 0:4f4ccb203a70 62 *
AjK 0:4f4ccb203a70 63 * All parameters are customisable which include:-
AjK 0:4f4ccb203a70 64 * <ul>
AjK 0:4f4ccb203a70 65 * <li> The sampling frequency. </li>
AjK 0:4f4ccb203a70 66 * <li> The number of continuous samples until a state change is detected. </li>
AjK 0:4f4ccb203a70 67 * <li> The number of continuous samples until a key is assumed held after a state change. </li>
AjK 0:4f4ccb203a70 68 * <li> The logic level which is assumed to be asserted (0volts or +volts). </li>
AjK 0:4f4ccb203a70 69 * </ul>
AjK 0:4f4ccb203a70 70 *
AjK 0:4f4ccb203a70 71 * Only callbacks that have been attached will be called by the library.
AjK 0:4f4ccb203a70 72 *
AjK 0:4f4ccb203a70 73 * Example:
AjK 0:4f4ccb203a70 74 * @code
AjK 0:4f4ccb203a70 75 * #include "mbed.h"
AjK 0:4f4ccb203a70 76 * #include "PinDetect.h"
AjK 0:4f4ccb203a70 77 *
AjK 0:4f4ccb203a70 78 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 79 * DigitialOut led1( LED1 );
AjK 0:4f4ccb203a70 80 * DigitialOut led2( LED2 );
AjK 0:4f4ccb203a70 81 * DigitialOut led3( LED3 );
AjK 0:4f4ccb203a70 82 * DigitialOut led4( LED4 );
AjK 0:4f4ccb203a70 83 *
AjK 0:4f4ccb203a70 84 * void keyPressed( void ) {
AjK 0:4f4ccb203a70 85 * led2 = 1;
AjK 0:4f4ccb203a70 86 * led3 = 0;
AjK 0:4f4ccb203a70 87 * led4 = 0;
AjK 0:4f4ccb203a70 88 * }
AjK 0:4f4ccb203a70 89 *
AjK 0:4f4ccb203a70 90 * void keyReleased( void ) {
AjK 0:4f4ccb203a70 91 * led2 = 0;
AjK 0:4f4ccb203a70 92 * led3 = 0;
AjK 0:4f4ccb203a70 93 * led4 = 0;
AjK 0:4f4ccb203a70 94 * }
AjK 0:4f4ccb203a70 95 *
AjK 0:4f4ccb203a70 96 * void keyPressedHeld( void ) {
AjK 0:4f4ccb203a70 97 * led3 = 1;
AjK 0:4f4ccb203a70 98 * }
AjK 0:4f4ccb203a70 99 *
AjK 0:4f4ccb203a70 100 * void keyReleasedHeld( void ) {
AjK 0:4f4ccb203a70 101 * led4 = 1;
AjK 0:4f4ccb203a70 102 * }
AjK 0:4f4ccb203a70 103 *
AjK 0:4f4ccb203a70 104 * int main() {
AjK 0:4f4ccb203a70 105 *
AjK 0:4f4ccb203a70 106 * pin.mode( PullDown );
AjK 0:4f4ccb203a70 107 * pin.attach_asserted( &keyPressed );
AjK 0:4f4ccb203a70 108 * pin.attach_deasserted( &keyReleased );
AjK 0:4f4ccb203a70 109 * pin.attach_asserted_held( &keyPressedHeld );
AjK 0:4f4ccb203a70 110 * pin.attach_deasserted_held( &keyReleasedHeld );
AjK 0:4f4ccb203a70 111 *
AjK 0:4f4ccb203a70 112 * // Sampling does not begin until you set a frequency.
AjK 0:4f4ccb203a70 113 * // The default is 20ms. If you want a different frequency
AjK 0:4f4ccb203a70 114 * // then pass the period in microseconds for example, for 10ms :-
AjK 0:4f4ccb203a70 115 * // pin.setSampleFrequency( 10000 );
AjK 0:4f4ccb203a70 116 * //
AjK 0:4f4ccb203a70 117 * pin.setSampleFrequency(); // Defaults to 20ms.
AjK 0:4f4ccb203a70 118 *
AjK 0:4f4ccb203a70 119 * while( 1 ) {
AjK 0:4f4ccb203a70 120 * led1 = !led1;
AjK 0:4f4ccb203a70 121 * wait( 0.2 );
AjK 0:4f4ccb203a70 122 * }
AjK 0:4f4ccb203a70 123 * }
AjK 0:4f4ccb203a70 124 * @endcode
AjK 0:4f4ccb203a70 125 *
AjK 0:4f4ccb203a70 126 * This example will flash led1 in a similar to a standard starting program.
AjK 0:4f4ccb203a70 127 *
AjK 0:4f4ccb203a70 128 * Applying a "1" (switch on) to pin 30 will switch on led2, removing the "1" to "0"
AjK 0:4f4ccb203a70 129 * (switch off) led2 goes out. Holding the "switch" at one for one second will switch
AjK 0:4f4ccb203a70 130 * on led3. An unasserted P30 (switched off) will, after one second illuminate led4
AjK 0:4f4ccb203a70 131 * when the deasserted calledback is called.
AjK 0:4f4ccb203a70 132 *
AjK 0:4f4ccb203a70 133 * The above is a very basic introduction. For more details:-
AjK 0:4f4ccb203a70 134 * @see example.h
AjK 0:4f4ccb203a70 135 */
AjK 0:4f4ccb203a70 136 class PinDetect {
AjK 1:611a8f5ac65c 137
Geremia 3:5ff38909c179 138
AjK 1:611a8f5ac65c 139
AjK 0:4f4ccb203a70 140 public:
AjK 0:4f4ccb203a70 141
AjK 0:4f4ccb203a70 142 /** PinDetect constructor
AjK 0:4f4ccb203a70 143 *
AjK 1:611a8f5ac65c 144 * By default the PinMode is set to PullDown.
AjK 1:611a8f5ac65c 145 *
AjK 0:4f4ccb203a70 146 * @see http://mbed.org/handbook/DigitalIn
AjK 0:4f4ccb203a70 147 * @param p PinName is a valid pin that supports DigitalIn
AjK 0:4f4ccb203a70 148 */
Geremia 3:5ff38909c179 149 PinDetect(PinName p, PinMode m, int assertvalue, unsigned int debounce_us, unsigned int held_us): interr(p), _assertvalue(assertvalue)
Geremia 3:5ff38909c179 150 {
Geremia 3:5ff38909c179 151 debouncetime=debounce_us;
Geremia 3:5ff38909c179 152 heldtime=held_us;
Geremia 3:5ff38909c179 153 bouncein=0;
Geremia 3:5ff38909c179 154 bounceout=0;
Geremia 3:5ff38909c179 155 disable();
Geremia 3:5ff38909c179 156 if (_assertvalue) { // pulse up
Geremia 3:5ff38909c179 157 interr.rise(this, &PinDetect::startpulse); // first rise then fall
Geremia 3:5ff38909c179 158 interr.fall(this, &PinDetect::endpulse);
AjK 1:611a8f5ac65c 159
Geremia 3:5ff38909c179 160 } else { // pulse down
Geremia 3:5ff38909c179 161 interr.fall(this, &PinDetect::startpulse); // first fall then rise
Geremia 3:5ff38909c179 162 interr.rise(this, &PinDetect::endpulse);
Geremia 3:5ff38909c179 163 }
Geremia 3:5ff38909c179 164 interr.mode(m);
Geremia 3:5ff38909c179 165 statereset(); // pinstate=S_IDLE;
Geremia 3:5ff38909c179 166 trig=false;
Geremia 3:5ff38909c179 167 enable();
AjK 0:4f4ccb203a70 168 }
AjK 0:4f4ccb203a70 169
AjK 0:4f4ccb203a70 170 /** PinDetect destructor
AjK 0:4f4ccb203a70 171 */
AjK 0:4f4ccb203a70 172 ~PinDetect() {
Geremia 3:5ff38909c179 173 interr.disable_irq();
Geremia 3:5ff38909c179 174 timeoutbounce.detach();
Geremia 3:5ff38909c179 175 timeoutheld.detach();
AjK 0:4f4ccb203a70 176 }
AjK 0:4f4ccb203a70 177
Geremia 3:5ff38909c179 178 void disable()
Geremia 3:5ff38909c179 179 {
Geremia 3:5ff38909c179 180 interr.disable_irq();
Geremia 3:5ff38909c179 181 statereset();
AjK 0:4f4ccb203a70 182 }
Geremia 3:5ff38909c179 183 void enable()
Geremia 3:5ff38909c179 184 {
Geremia 3:5ff38909c179 185 interr.enable_irq();
Geremia 3:5ff38909c179 186 statereset();
Geremia 3:5ff38909c179 187 }
AjK 0:4f4ccb203a70 188
AjK 0:4f4ccb203a70 189 /** Set the number of continuous samples until assert assumed.
AjK 0:4f4ccb203a70 190 *
AjK 0:4f4ccb203a70 191 * Defaults to 1 (1 * sample frequency).
AjK 0:4f4ccb203a70 192 *
AjK 0:4f4ccb203a70 193 * @param int The number of continuous samples until assert assumed.
AjK 0:4f4ccb203a70 194 */
Geremia 3:5ff38909c179 195 void setDebounceTime(int i) { debouncetime = i; }
AjK 0:4f4ccb203a70 196
AjK 0:4f4ccb203a70 197 /** Set the number of continuous samples until held assumed.
AjK 0:4f4ccb203a70 198 *
AjK 0:4f4ccb203a70 199 * Defaults to 50 * sample frequency.
AjK 0:4f4ccb203a70 200 *
AjK 0:4f4ccb203a70 201 * @param int The number of continuous samples until held assumed.
AjK 0:4f4ccb203a70 202 */
Geremia 3:5ff38909c179 203 void setHeldTime(int i) { heldtime = i; }
Geremia 3:5ff38909c179 204
AjK 0:4f4ccb203a70 205
AjK 0:4f4ccb203a70 206 /** Attach a callback function
AjK 0:4f4ccb203a70 207 *
AjK 0:4f4ccb203a70 208 * @code
AjK 0:4f4ccb203a70 209 *
AjK 0:4f4ccb203a70 210 * DigitalOut led1( LED1 );
AjK 0:4f4ccb203a70 211 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 212 *
AjK 0:4f4ccb203a70 213 * void myCallback( void ) {
AjK 0:4f4ccb203a70 214 * led1 = 1;
AjK 0:4f4ccb203a70 215 * };
AjK 0:4f4ccb203a70 216 *
AjK 0:4f4ccb203a70 217 * main() {
AjK 0:4f4ccb203a70 218 * pin.attach_asserted( &myCallback );
AjK 0:4f4ccb203a70 219 * }
AjK 0:4f4ccb203a70 220 *
AjK 0:4f4ccb203a70 221 * @endcode
AjK 0:4f4ccb203a70 222 *
AjK 0:4f4ccb203a70 223 * Call this function when a pin is asserted.
AjK 0:4f4ccb203a70 224 * @param function A C function pointer
AjK 0:4f4ccb203a70 225 */
AjK 0:4f4ccb203a70 226 void attach_asserted(void (*function)(void)) {
Geremia 3:5ff38909c179 227 callbackAsserted.attach( function );
AjK 0:4f4ccb203a70 228 }
AjK 0:4f4ccb203a70 229
AjK 0:4f4ccb203a70 230 /** Attach a callback object/method
AjK 0:4f4ccb203a70 231 *
AjK 0:4f4ccb203a70 232 * @code
AjK 0:4f4ccb203a70 233 *
AjK 0:4f4ccb203a70 234 * class Bar {
AjK 0:4f4ccb203a70 235 * public:
AjK 0:4f4ccb203a70 236 * void myCallback( void ) { led1 = 1; }
AjK 0:4f4ccb203a70 237 * };
AjK 0:4f4ccb203a70 238 *
AjK 0:4f4ccb203a70 239 * DigitalOut led1( LED1 );
AjK 0:4f4ccb203a70 240 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 241 * Bar bar;
AjK 0:4f4ccb203a70 242 *
AjK 0:4f4ccb203a70 243 * main() {
AjK 0:4f4ccb203a70 244 * pin.attach_asserted( &bar, &Bar::myCallback );
AjK 0:4f4ccb203a70 245 * }
AjK 0:4f4ccb203a70 246 *
AjK 0:4f4ccb203a70 247 * @endcode
AjK 0:4f4ccb203a70 248 *
AjK 0:4f4ccb203a70 249 * Call this function when a pin is asserted.
AjK 0:4f4ccb203a70 250 * @param object An object that conatins the callback method.
AjK 0:4f4ccb203a70 251 * @param method The method within the object to call.
AjK 0:4f4ccb203a70 252 */
AjK 0:4f4ccb203a70 253 template<typename T>
AjK 0:4f4ccb203a70 254 void attach_asserted(T *object, void (T::*member)(void)) {
Geremia 3:5ff38909c179 255 callbackAsserted.attach( object, member );
AjK 0:4f4ccb203a70 256 }
AjK 0:4f4ccb203a70 257
AjK 0:4f4ccb203a70 258 /** Attach a callback function
AjK 0:4f4ccb203a70 259 *
AjK 0:4f4ccb203a70 260 * @code
AjK 0:4f4ccb203a70 261 *
AjK 0:4f4ccb203a70 262 * DigitalOut led1( LED1 );
AjK 0:4f4ccb203a70 263 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 264 *
AjK 0:4f4ccb203a70 265 * void myCallback( void ) {
AjK 0:4f4ccb203a70 266 * led1 = 0;
AjK 0:4f4ccb203a70 267 * };
AjK 0:4f4ccb203a70 268 *
AjK 0:4f4ccb203a70 269 * main() {
AjK 0:4f4ccb203a70 270 * pin.attach_deasserted( &myCallback );
AjK 0:4f4ccb203a70 271 * }
AjK 0:4f4ccb203a70 272 *
AjK 0:4f4ccb203a70 273 * @endcode
AjK 0:4f4ccb203a70 274 *
AjK 0:4f4ccb203a70 275 * Call this function when a pin is deasserted.
AjK 0:4f4ccb203a70 276 * @param function A C function pointer
AjK 0:4f4ccb203a70 277 */
AjK 0:4f4ccb203a70 278 void attach_deasserted(void (*function)(void)) {
Geremia 3:5ff38909c179 279 callbackDeasserted.attach( function );
AjK 0:4f4ccb203a70 280 }
AjK 0:4f4ccb203a70 281
AjK 0:4f4ccb203a70 282 /** Attach a callback object/method
AjK 0:4f4ccb203a70 283 *
AjK 0:4f4ccb203a70 284 * @code
AjK 0:4f4ccb203a70 285 *
AjK 0:4f4ccb203a70 286 * class Bar {
AjK 0:4f4ccb203a70 287 * public:
AjK 0:4f4ccb203a70 288 * void myCallback( void ) { led1 = 0; }
AjK 0:4f4ccb203a70 289 * };
AjK 0:4f4ccb203a70 290 *
AjK 0:4f4ccb203a70 291 * DigitalOut led1( LED1 );
AjK 0:4f4ccb203a70 292 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 293 * Bar bar;
AjK 0:4f4ccb203a70 294 *
AjK 0:4f4ccb203a70 295 * main() {
AjK 0:4f4ccb203a70 296 * pin.attach_deasserted( &bar, &Bar::myCallback );
AjK 0:4f4ccb203a70 297 * }
AjK 0:4f4ccb203a70 298 *
AjK 0:4f4ccb203a70 299 * @endcode
AjK 0:4f4ccb203a70 300 *
AjK 0:4f4ccb203a70 301 * Call this function when a pin is deasserted.
AjK 0:4f4ccb203a70 302 * @param object An object that conatins the callback method.
AjK 0:4f4ccb203a70 303 * @param method The method within the object to call.
AjK 0:4f4ccb203a70 304 */
AjK 0:4f4ccb203a70 305 template<typename T>
AjK 0:4f4ccb203a70 306 void attach_deasserted(T *object, void (T::*member)(void)) {
Geremia 3:5ff38909c179 307 callbackDeasserted.attach( object, member );
AjK 0:4f4ccb203a70 308 }
AjK 0:4f4ccb203a70 309
AjK 0:4f4ccb203a70 310 /** Attach a callback function
AjK 0:4f4ccb203a70 311 *
AjK 0:4f4ccb203a70 312 * @code
AjK 0:4f4ccb203a70 313 *
AjK 0:4f4ccb203a70 314 * DigitalOut led2( LED2 );
AjK 0:4f4ccb203a70 315 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 316 *
AjK 0:4f4ccb203a70 317 * void myCallback( void ) {
AjK 0:4f4ccb203a70 318 * led2 = 1;
AjK 0:4f4ccb203a70 319 * };
AjK 0:4f4ccb203a70 320 *
AjK 0:4f4ccb203a70 321 * main() {
AjK 0:4f4ccb203a70 322 * pin.attach_asserted_held( &myCallback );
AjK 0:4f4ccb203a70 323 * }
AjK 0:4f4ccb203a70 324 *
AjK 0:4f4ccb203a70 325 * @endcode
AjK 0:4f4ccb203a70 326 *
AjK 0:4f4ccb203a70 327 * Call this function when a pin is asserted and held.
AjK 0:4f4ccb203a70 328 * @param function A C function pointer
AjK 0:4f4ccb203a70 329 */
AjK 0:4f4ccb203a70 330 void attach_asserted_held(void (*function)(void)) {
Geremia 3:5ff38909c179 331 callbackAssertedHeld.attach( function );
AjK 0:4f4ccb203a70 332 }
AjK 0:4f4ccb203a70 333
AjK 0:4f4ccb203a70 334 /** Attach a callback object/method
AjK 0:4f4ccb203a70 335 *
AjK 0:4f4ccb203a70 336 * @code
AjK 0:4f4ccb203a70 337 *
AjK 0:4f4ccb203a70 338 * class Bar {
AjK 0:4f4ccb203a70 339 * public:
AjK 0:4f4ccb203a70 340 * void myCallback( void ) { led2 = 0; }
AjK 0:4f4ccb203a70 341 * };
AjK 0:4f4ccb203a70 342 *
AjK 0:4f4ccb203a70 343 * DigitalOut led2( LED2 );
AjK 0:4f4ccb203a70 344 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 345 * Bar bar;
AjK 0:4f4ccb203a70 346 *
AjK 0:4f4ccb203a70 347 * main() {
AjK 0:4f4ccb203a70 348 * pin.attach_asserted_held( &bar, &Bar::myCallback );
AjK 0:4f4ccb203a70 349 * }
AjK 0:4f4ccb203a70 350 *
AjK 0:4f4ccb203a70 351 * @endcode
AjK 0:4f4ccb203a70 352 *
AjK 0:4f4ccb203a70 353 * Call this function when a pin is asserted and held.
AjK 0:4f4ccb203a70 354 * @param object An object that conatins the callback method.
AjK 0:4f4ccb203a70 355 * @param method The method within the object to call.
AjK 0:4f4ccb203a70 356 */
AjK 0:4f4ccb203a70 357 template<typename T>
AjK 0:4f4ccb203a70 358 void attach_asserted_held(T *object, void (T::*member)(void)) {
Geremia 3:5ff38909c179 359 callbackAssertedHeld.attach( object, member );
AjK 0:4f4ccb203a70 360 }
AjK 0:4f4ccb203a70 361
AjK 0:4f4ccb203a70 362 /** Attach a callback function
AjK 0:4f4ccb203a70 363 *
AjK 0:4f4ccb203a70 364 * @code
AjK 0:4f4ccb203a70 365 *
AjK 0:4f4ccb203a70 366 * DigitalOut led3( LED3 );
AjK 0:4f4ccb203a70 367 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 368 *
AjK 0:4f4ccb203a70 369 * void myCallback( void ) {
AjK 0:4f4ccb203a70 370 * led3 = 1;
AjK 0:4f4ccb203a70 371 * };
AjK 0:4f4ccb203a70 372 *
AjK 0:4f4ccb203a70 373 * main() {
AjK 0:4f4ccb203a70 374 * pin.attach_deasserted_held( &myCallback );
AjK 0:4f4ccb203a70 375 * }
AjK 0:4f4ccb203a70 376 *
AjK 0:4f4ccb203a70 377 * @endcode
AjK 0:4f4ccb203a70 378 *
AjK 0:4f4ccb203a70 379 * Call this function when a pin is deasserted and held.
AjK 0:4f4ccb203a70 380 * @param function A C function pointer
AjK 0:4f4ccb203a70 381 */
AjK 0:4f4ccb203a70 382 void attach_deasserted_held(void (*function)(void)) {
Geremia 3:5ff38909c179 383 callbackDeassertedHeld.attach( function );
AjK 0:4f4ccb203a70 384 }
AjK 0:4f4ccb203a70 385
AjK 0:4f4ccb203a70 386 /** Attach a callback object/method
AjK 0:4f4ccb203a70 387 *
AjK 0:4f4ccb203a70 388 * @code
AjK 0:4f4ccb203a70 389 *
AjK 0:4f4ccb203a70 390 * class Bar {
AjK 0:4f4ccb203a70 391 * public:
AjK 0:4f4ccb203a70 392 * void myCallback( void ) { led3 = 0; }
AjK 0:4f4ccb203a70 393 * };
AjK 0:4f4ccb203a70 394 *
AjK 0:4f4ccb203a70 395 * DigitalOut led3( LED3 );
AjK 0:4f4ccb203a70 396 * PinDetect pin( p30 );
AjK 0:4f4ccb203a70 397 * Bar bar;
AjK 0:4f4ccb203a70 398 *
AjK 0:4f4ccb203a70 399 * main() {
AjK 0:4f4ccb203a70 400 * pin.attach_deasserted_held( &bar, &Bar::myCallback );
AjK 0:4f4ccb203a70 401 * }
AjK 0:4f4ccb203a70 402 *
AjK 0:4f4ccb203a70 403 * @endcode
AjK 0:4f4ccb203a70 404 *
AjK 0:4f4ccb203a70 405 * Call this function when a pin is deasserted and held.
AjK 0:4f4ccb203a70 406 * @param object An object that conatins the callback method.
AjK 0:4f4ccb203a70 407 * @param method The method within the object to call.
AjK 0:4f4ccb203a70 408 */
AjK 0:4f4ccb203a70 409 template<typename T>
AjK 0:4f4ccb203a70 410 void attach_deasserted_held(T *object, void (T::*member)(void)) {
Geremia 3:5ff38909c179 411 callbackDeassertedHeld.attach( object, member );
AjK 0:4f4ccb203a70 412 }
AjK 0:4f4ccb203a70 413
AjK 0:4f4ccb203a70 414 /** operator int()
AjK 0:4f4ccb203a70 415 *
AjK 0:4f4ccb203a70 416 * Read the value of the pin being sampled.
AjK 0:4f4ccb203a70 417 */
Geremia 3:5ff38909c179 418 operator int() { return interr.read(); }
Geremia 3:5ff38909c179 419
Geremia 3:5ff38909c179 420 /** Get the current pin state
Geremia 3:5ff38909c179 421 *
Geremia 3:5ff38909c179 422 * @return pinstate bitmask S_HELD|S_ASSERTED|S_RINGING, 0=S_IDLE
AjK 0:4f4ccb203a70 423 */
Geremia 3:5ff38909c179 424 unsigned int state()
Geremia 3:5ff38909c179 425 {
Geremia 3:5ff38909c179 426 return pinstate;
Geremia 3:5ff38909c179 427 }
AjK 0:4f4ccb203a70 428
Geremia 3:5ff38909c179 429 /** Reset pinstate to S_IDLE and reset debounce/held timers
Geremia 3:5ff38909c179 430 *
Geremia 3:5ff38909c179 431 * @return pinstate bitmask S_HELD|S_ASSERTED|S_RINGING, 0=S_IDLE
Geremia 3:5ff38909c179 432 */
Geremia 3:5ff38909c179 433 void statereset()
Geremia 3:5ff38909c179 434 {
Geremia 3:5ff38909c179 435 pinstate=S_IDLE;
Geremia 3:5ff38909c179 436 timeoutheld.detach();
Geremia 3:5ff38909c179 437 timeoutbounce.detach();
Geremia 3:5ff38909c179 438 pinstate=S_IDLE;
Geremia 3:5ff38909c179 439 }
Geremia 3:5ff38909c179 440 unsigned int getbouncein()
Geremia 3:5ff38909c179 441 {
Geremia 3:5ff38909c179 442 return bouncein;
Geremia 3:5ff38909c179 443 }
Geremia 3:5ff38909c179 444 unsigned int getbounceout()
Geremia 3:5ff38909c179 445 {
Geremia 3:5ff38909c179 446 return bounceout;
Geremia 3:5ff38909c179 447 }
Geremia 3:5ff38909c179 448
Geremia 3:5ff38909c179 449 protected:
Geremia 3:5ff38909c179 450
Geremia 3:5ff38909c179 451 void startpulse()
Geremia 3:5ff38909c179 452 {
Geremia 3:5ff38909c179 453 pinstate|=S_RINGING;
Geremia 3:5ff38909c179 454 if((pinstate&S_ASSERTED)==0) timeoutbounce.attach_us(this, &PinDetect::onasserted, debouncetime);
Geremia 3:5ff38909c179 455 // else if state is asserted and we are here, it means we are debouncing transition to deasserted, timeout is already attached to ondeasserted()
Geremia 3:5ff38909c179 456 trig=true; // ISR completed
Geremia 3:5ff38909c179 457 }
Geremia 3:5ff38909c179 458
Geremia 3:5ff38909c179 459 void endpulse()
Geremia 3:5ff38909c179 460 {
Geremia 3:5ff38909c179 461 if(!trig) return; // first check if the previous startpulse ISR completed
Geremia 3:5ff38909c179 462 pinstate|=S_RINGING;
Geremia 3:5ff38909c179 463
Geremia 3:5ff38909c179 464 if((pinstate&S_ASSERTED)!=0) // if was asserted or held asserted, debounce transition to deasserted
Geremia 3:5ff38909c179 465 {
Geremia 3:5ff38909c179 466 timeoutheld.detach();
Geremia 3:5ff38909c179 467 timeoutbounce.attach_us(this, &PinDetect::ondeasserted, debouncetime);
AjK 0:4f4ccb203a70 468 }
Geremia 3:5ff38909c179 469 trig=false;
Geremia 3:5ff38909c179 470 }
Geremia 3:5ff38909c179 471
Geremia 3:5ff38909c179 472 void onasserted()
Geremia 3:5ff38909c179 473 {
Geremia 3:5ff38909c179 474 if(interr.read()!=_assertvalue)
Geremia 3:5ff38909c179 475 {
Geremia 3:5ff38909c179 476 bouncein++;
Geremia 3:5ff38909c179 477 return; // was a bounce
AjK 0:4f4ccb203a70 478 }
Geremia 3:5ff38909c179 479 pinstate|=S_ASSERTED; // set asserted
Geremia 3:5ff38909c179 480 pinstate&= ~(S_RINGING|S_HELD); // clear ringing and held
Geremia 3:5ff38909c179 481 timeoutheld.attach_us(this, &PinDetect::onheld, heldtime);
Geremia 3:5ff38909c179 482 callbackAsserted.call(); // call function for pin state change (deasserted -> asserted)
AjK 0:4f4ccb203a70 483 }
AjK 0:4f4ccb203a70 484
Geremia 3:5ff38909c179 485 void onheld()
Geremia 3:5ff38909c179 486 {
Geremia 3:5ff38909c179 487 if((pinstate&S_RINGING)!=0 || (pinstate&S_ASSERTED)==0 || (interr.read()!=_assertvalue)) return; // to be valid, needs ringing=false asserted=true pinread=assertvalue
Geremia 3:5ff38909c179 488 pinstate|=S_HELD; // set held
Geremia 3:5ff38909c179 489 callbackAssertedHeld.call(); // call function for pin state change (asserted -> held asserted)
Geremia 3:5ff38909c179 490 }
Geremia 3:5ff38909c179 491
Geremia 3:5ff38909c179 492 void ondeasserted()
Geremia 3:5ff38909c179 493 {
Geremia 3:5ff38909c179 494 if((pinstate&(S_ASSERTED))==0) return; // pinstate was reset externally
Geremia 3:5ff38909c179 495 if(interr.read()==_assertvalue)
Geremia 3:5ff38909c179 496 {
Geremia 3:5ff38909c179 497 bounceout++;
Geremia 3:5ff38909c179 498 return; // was a bounce
Geremia 3:5ff38909c179 499 }
Geremia 3:5ff38909c179 500 if((pinstate&S_HELD)==0) callbackDeasserted.call(); // call function for pin state change (asserted -> deasserted)(quick pulse)
Geremia 3:5ff38909c179 501 else callbackDeassertedHeld.call(); // call function for pin state change (held asserted -> deasserted)(long pulse)
Geremia 3:5ff38909c179 502 pinstate=S_IDLE;
Geremia 3:5ff38909c179 503 }
Geremia 3:5ff38909c179 504
Geremia 3:5ff38909c179 505 private:
Geremia 3:5ff38909c179 506 InterruptIn interr;
Geremia 3:5ff38909c179 507 Timeout timeoutbounce;
Geremia 3:5ff38909c179 508 Timeout timeoutheld;
Geremia 3:5ff38909c179 509 unsigned int debouncetime;
Geremia 3:5ff38909c179 510 unsigned int heldtime;
Geremia 3:5ff38909c179 511 int _assertvalue;
Geremia 3:5ff38909c179 512 FunctionPointer callbackAsserted;
Geremia 3:5ff38909c179 513 FunctionPointer callbackDeasserted;
Geremia 3:5ff38909c179 514 FunctionPointer callbackAssertedHeld;
Geremia 3:5ff38909c179 515 FunctionPointer callbackDeassertedHeld;
Geremia 3:5ff38909c179 516 volatile unsigned int pinstate;
Geremia 3:5ff38909c179 517 volatile unsigned int bouncein;
Geremia 3:5ff38909c179 518 volatile unsigned int bounceout;
Geremia 3:5ff38909c179 519
Geremia 3:5ff38909c179 520 bool trig;
Geremia 3:5ff38909c179 521
AjK 0:4f4ccb203a70 522 };
AjK 0:4f4ccb203a70 523
AjK 0:4f4ccb203a70 524
AjK 0:4f4ccb203a70 525 #endif