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

Files at this revision

API Documentation at this revision

Comitter:
hilgo
Date:
Sun Feb 20 18:47:18 2011 +0000
Commit message:
Initial revision, tested with the example provided.

Changed in this revision

RepeatButton.cpp Show annotated file Show diff for this revision Revisions of this file
RepeatButton.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RepeatButton.cpp	Sun Feb 20 18:47:18 2011 +0000
@@ -0,0 +1,110 @@
+/* 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.
+ */
+
+#include "mbed.h"
+#include "RepeatButton.h"
+
+KeyBuffer::KeyBuffer(int size)
+{
+    // One byte cannot be used; if it were 
+    // used, the buffer empty condition
+    // mReadIndex == mWriteIndex would apply.
+    // So one byte extra is allocated. 
+    mBuffer = new uint8_t[size+1];
+    mSize = size+1;
+    mReadIndex = 0;
+    mWriteIndex = 0;
+}
+
+KeyBuffer::~KeyBuffer()
+{
+    delete mBuffer;
+}
+
+void KeyBuffer::Write(uint8_t value)
+{
+    int nextIndex = mWriteIndex + 1;
+    if(nextIndex >= mSize)
+        nextIndex = 0;
+    if(nextIndex == mReadIndex)
+    {
+        // Buffer full!
+        return;
+    }
+    mBuffer[mWriteIndex] = value;
+    mWriteIndex = nextIndex;
+}
+
+int KeyBuffer::Read()
+{
+    if(mReadIndex == mWriteIndex)
+    {
+        // Buffer empty!
+        return -1;
+    }
+    int value = mBuffer[mReadIndex];
+    int nextIndex = mReadIndex + 1;
+    if(nextIndex >= mSize)
+        nextIndex = 0;
+    mReadIndex = nextIndex;
+    return value;
+}
+
+
+RepeatButton::RepeatButton(PinName pin, int delay_ms, int period_ms, KeyBuffer *buf, char value) :
+    mIn(pin),
+    mIrq(pin) 
+{
+    mIn.mode(PullUp);
+    mValue = value;
+    mDelay = delay_ms * 1000;
+    mPeriod = period_ms * 1000;
+    mIrq.rise(this, &RepeatButton::OnChange);
+    mIrq.fall(this, &RepeatButton::OnChange);
+    mTarget = buf;
+}
+
+void RepeatButton::OnChange()
+{
+    // Any change on input. Wait 5ms to get rid of bounce and get reading afterwards.
+    mTimeout.attach_us(this, &RepeatButton::OnBounce, 5000);
+}
+
+void RepeatButton::OnBounce()
+{
+    if(mIn == 0)
+    {
+        // Key is still pressed. Generate first press.
+        mTimeout.attach_us(this, &RepeatButton::OnRepeat, mDelay);
+        mTarget->Write(mValue);
+    }
+}
+
+void RepeatButton::OnRepeat()
+{
+    if(mIn == 0)
+    {
+        // Key is still pressed. Generate repeated press.
+        mTimeout.attach_us(this, &RepeatButton::OnRepeat, mPeriod);
+        mTarget->Write(mValue);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RepeatButton.h	Sun Feb 20 18:47:18 2011 +0000
@@ -0,0 +1,164 @@
+/* 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__