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.cpp

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.
 */

#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);
    }
}