11

Dependents:   Program_R11

keypad.cpp

Committer:
gj_schoneveld
Date:
2012-11-04
Revision:
13:fb6929fac0db
Parent:
12:e6623f165199
Child:
14:f6c3647bf421

File content as of revision 13:fb6929fac0db:

#include "keypad.h"

Keypad::Keypad(PinName row3, PinName row2, PinName row1, PinName row0,
               PinName col3, PinName col2, PinName col1, PinName col0,
               int debounce_ms):
    _row0(row0), _row1(row1), _row2(row2), _row3(row3),
    _cols(col0, col1, col2, col3)
{
    _debounce = debounce_ms;
    _rows[0] = &_row0;
    _rows[1] = &_row1;
    _rows[2] = &_row2;
    _rows[3] = &_row3;
    for (int r = 0; r < row_count; r++)
        _rows[r]->mode(PullUp);
    _cols.mode(OpenDrain);
    _cols.output();
}

void Keypad::_setupFallTrigger(void)
{
    for (int r = 0; r < row_count; r++)
        _rows[r]->fall(this, &Keypad::_callback);
}

void Keypad::Start(void)
{
    /* make the columns zero so they can pull rows down */
    _cols = 0x00;
}

void Keypad::Stop(void)
{
    /* make the columns one so they cannot pull any rows down anymore */
    _cols = ~0x00;
}

void Keypad::CallAfterInput(uint32_t (*fptr)(uint32_t index))
{
    _input.attach(fptr);
    _setupFallTrigger();
}

int Keypad::DebouncedScan()
{
    /* debounce */
    int key1 = Scan();
    
    wait_ms(_debounce);
    
    int key2 = Scan();
    
    if (key1 != key2)
        return -1;
    else
        return key1;
}

int Keypad::Scan()
{
    /* lookup row */
    int r = -1;
    for (r = 0; r < row_count; r++) {
        if (*_rows[r] == 0)
            break;
    }

    /* if we didn't find a valid row, return */
    if (!(0 <= r && r < row_count))
        return -1;

    /* scan columns to find out which one pulls down the row */ 
    int c = -1;
    for (c = 0; c < col_count; c++) {
        _cols = ~(1 << c);
        if (*_rows[r] == 0)
            break;
    }

    /* re-energize all columns */
    Start();

    /* if we didn't find a valid column, return */
    if (!(0 <= c && c < col_count))
        return -1;

    return r * col_count + c;
}
int Keypad::DebouncedScanMultiple()
{
    /* debounce */
    int key1 = ScanMultiple();
    
    wait_ms(_debounce);
    
    int key2 = ScanMultiple();
    
    return key1 & key2;
}

int Keypad::ScanMultiple()
{
    int res = 0;    
    
    int i = 0;
    for (int c = 0; c < col_count; c++) {
        _cols = ~(1 << c);
        for (int r = 0; r < row_count; r++) {
            if (*_rows[r] == 0) {
                res |= 1 << (r * col_count + c);
            }
            i++;
        }
    }
    
    return res;
}

void Keypad::_callback()
{
    /* lookup */
    int position = DebouncedScan();
    
    /* call back a valid position */
    if (position >= 0)
        _input.call(position);
}