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
Revision 0:8be79829ce90, committed 2011-02-20
- 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 |
diff -r 000000000000 -r 8be79829ce90 RepeatButton.cpp --- /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
diff -r 000000000000 -r 8be79829ce90 RepeatButton.h --- /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__