This library improves behaviour of push buttons. The automatic repeat is very convenient for e.g. entering time with up/down buttons. The library buffers presses, so no presses are missed.

Dependents:   Thermostat_NucleoF401

RepeatButton.h

Committer:
hilgo
Date:
2011-02-20
Revision:
0:8be79829ce90

File content as of revision 0:8be79829ce90:

/* mbed RepeatButton Library
 * Copyright (c) 2011 Jeroen Hilgers
 *
 * 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 __REPEAT_BUTTON_H__
#define __REPEAT_BUTTON_H__

/** KeyBuffer and RepeatButton classes.
 **
 ** The RepeatButton provides removal of contact bounce and repeat 
 ** functionality. The repeat functionality works similar to that of 
 ** a PC keyboard. If you press a key, it will register once. If you 
 ** keep the key down, it will start repeating after a small delay.
 **
 ** The KeyBuffer class provides a key buffer functionality. It stores
 ** presses and repeats from one or more RepeatButton instances untill
 ** the main loop requests them.
 *  
 *
 * Example:
 * @code
 * #include "mbed.h"
 * #include "RepeatButton.h"
 *
 * Serial pc(USBTX, USBRX);
 *
 * #define REPEAT_DELAY 500
 * #define REPEAT_PERIOD 100
 * #define KEY_LEFT 1
 * #define KEY_UP 2
 * #define KEY_RIGHT 3
 * #define KEY_DOWN 4
 * #define KEY_PUSH 5
 * 
 * KeyBuffer TheKeyBuffer(32);
 * 
 * RepeatButton naviLeft(p5, REPEAT_DELAY, REPEAT_PERIOD, &TheKeyBuffer, KEY_LEFT);
 * RepeatButton naviUp(p6, REPEAT_DELAY, REPEAT_PERIOD, &TheKeyBuffer, KEY_UP);
 * RepeatButton naviRight(p7, REPEAT_DELAY, REPEAT_PERIOD, &TheKeyBuffer, KEY_RIGHT);
 * RepeatButton naviDown(p9, REPEAT_DELAY, REPEAT_PERIOD, &TheKeyBuffer, KEY_DOWN);
 * RepeatButton naviPush(p8, REPEAT_DELAY, REPEAT_PERIOD, &TheKeyBuffer, KEY_PUSH);
 * 
 * DigitalOut led1(LED1);
 * 
 * int main() 
 * {
 *     int x=0, y=0, value;
 *     pc.baud(115200);
 *     pc.printf("Repeat key demo.\r\n");
 *     while(1) 
 *     {
 *         // Read TheKeyBuffer until empty.
 *         for(value = TheKeyBuffer.Read(); value != -1; value = TheKeyBuffer.Read())
 *         {
 *             switch(value)
 *             {
 *                 case KEY_LEFT:
 *                     x--;
 *                 break;
 *                 
 *                 case KEY_RIGHT:
 *                     x++;
 *                 break;
 *                 
 *                 case KEY_DOWN:
 *                     y--;
 *                 break;
 *                 
 *                 case KEY_UP:
 *                     y++;
 *                 break;
 *                 
 *                 case KEY_PUSH:
 *                     x = 0;
 *                     y = 0;
 *                 break;
 *             }
 *         }
 *         pc.printf("(x, y) = (%d, %d)\r\n", x, y);
 *         wait(0.05);
 *         led1 = led1^1;
 *     }
 * }
 *  
 * @endcode
 */


class KeyBuffer
{
    public:
        /** Create a KeyBuffer object and initizalize it.
         *
         * @param size Number of button events that can be stored in the buffer.
         */    
        KeyBuffer(int size);
        ~KeyBuffer();
        /** Add a press or repeat to the buffer.
         *
         * @param value Identifier for the key pressed.
         */    
        void Write(uint8_t value);
        /** Check if there is anything waiting in the buffer.
         *
         * @return value Returns -1 if the buffer is empty. Otherwise, the next value is returned and removed from the buffer.
         */    
        int Read();
    private:
        int mSize;
        int mReadIndex;
        int mWriteIndex;
        uint8_t *mBuffer;
};


class RepeatButton
{
    public:
        /** Create a RepeatButton object and initizalize it.
         *
         * @param pin The mbed pin to which the button is connected. A PullUp is connected to this pin, so it should connect to ground.
         * @param delay_ms The number of ms before the first repeat.
         * @param period_ms The number of ms between each repeat.
         * @param buf Pointer to the KeyBuffer instance where this RepeatButton can store its events.
         * @param value Value for the key. Needed to discriminate between different keys going into the same buffer.
         */    
        RepeatButton(PinName pin, int delay_ms, int period_ms, KeyBuffer *buf, char value);
   private:
        void OnChange(); // Called on rising/falling edge. 
        
        Timeout mTimeout;
        
        void OnBounce(); // Called upon expiracy of bounce delay.
        void OnRepeat(); // Called upon expiracy of delay / repeat period.

        DigitalIn mIn;
        InterruptIn mIrq;
        
        char mValue;
        int mDelay;
        int mPeriod;
        
        KeyBuffer *mTarget; // Reference to target buffer.
};

#endif // __REPEAT_BUTTON_H__