3x4 keypad library (Extended not only 3x4 but 4x4,4x5 and 5x5 keys)

Dependents:   Keypad_input_OS2 Keypad_input

see /users/kenjiArai/notebook/keypadkey-matrix--control/

Keypad.cpp

Committer:
kenjiArai
Date:
2020-04-13
Revision:
4:f74ca02cdba1
Parent:
3:0ea41738b560
Child:
5:8929ce2f393c

File content as of revision 4:f74ca02cdba1:

/*
 * Mbed Library
 *  example:
 *      Akizuki AE-KIT45-KEYPAD4X3
 *      http://akizukidenshi.com/catalog/g/gK-12229/
 *
 * Copyright (c) 2017,'20 Kenji Arai / JH1PJL
 *  http://www7b.biglobe.ne.jp/~kenjia/
 *  https://os.mbed.com/users/kenjiArai/
 *      Created:    September 27th, 2017
 *      Revised:    April     13th, 2020
 */

#include "Keypad.h"

//#define DEBUG_LED     // for debug

#if defined(DEBUG_LED)
extern DigitalOut my_led;
#define LEDON   {my_led=1;}
#define LEDOFF  {my_led=0;}
#else
#define LEDON   {;}
#define LEDOFF  {;}
#endif

Keypad::Keypad(
    PinName kx, PinName ky, PinName kz,
    PinName ka, PinName kb, PinName kc, PinName kd
)
{
    k_in[0]  = new DigitalIn(ka, PullUp);
    k_in[1]  = new DigitalIn(kb, PullUp);
    k_in[2]  = new DigitalIn(kc, PullUp);
    k_in[3]  = new DigitalIn(kd, PullUp);
    k_out[0] = new DigitalInOut(kx, PIN_OUTPUT, OpenDrain, 1);
    k_out[1] = new DigitalInOut(ky, PIN_OUTPUT, OpenDrain, 1);
    k_out[2] = new DigitalInOut(kz, PIN_OUTPUT, OpenDrain, 1);
    key_mode    = 12;
    key_in_num  = 4;
    key_out_num = 3;
    initialize();
}

Keypad::Keypad(
    PinName kx, PinName ky, PinName kz, PinName kw,
    PinName ka, PinName kb, PinName kc, PinName kd
)
{
    k_in[0]  = new DigitalIn(ka, PullUp);
    k_in[1]  = new DigitalIn(kb, PullUp);
    k_in[2]  = new DigitalIn(kc, PullUp);
    k_in[3]  = new DigitalIn(kd, PullUp);
    k_out[0] = new DigitalInOut(kx, PIN_OUTPUT, OpenDrain, 1);
    k_out[1] = new DigitalInOut(ky, PIN_OUTPUT, OpenDrain, 1);
    k_out[2] = new DigitalInOut(kz, PIN_OUTPUT, OpenDrain, 1);
    k_out[3] = new DigitalInOut(kw, PIN_OUTPUT, OpenDrain, 1);
    key_mode    = 16;
    key_in_num  = 4;
    key_out_num = 4;
    initialize();
}

Keypad::Keypad(
    PinName kx, PinName ky, PinName kz, PinName kw,
    PinName ka, PinName kb, PinName kc, PinName kd, PinName ke
)
{
    k_in[0]  = new DigitalIn(ka, PullUp);
    k_in[1]  = new DigitalIn(kb, PullUp);
    k_in[2]  = new DigitalIn(kc, PullUp);
    k_in[3]  = new DigitalIn(kd, PullUp);
    k_in[4]  = new DigitalIn(ke, PullUp);
    k_out[0] = new DigitalInOut(kx, PIN_OUTPUT, OpenDrain, 1);
    k_out[1] = new DigitalInOut(ky, PIN_OUTPUT, OpenDrain, 1);
    k_out[2] = new DigitalInOut(kz, PIN_OUTPUT, OpenDrain, 1);
    k_out[3] = new DigitalInOut(kw, PIN_OUTPUT, OpenDrain, 1);
    key_mode    = 20;
    key_in_num  = 5;
    key_out_num = 4;
    initialize();
}

Keypad::Keypad(
    PinName kx, PinName ky, PinName kz, PinName kw, PinName kv,
    PinName ka, PinName kb, PinName kc, PinName kd, PinName ke
)
{
    k_in[0]  = new DigitalIn(ka, PullUp);
    k_in[1]  = new DigitalIn(kb, PullUp);
    k_in[2]  = new DigitalIn(kc, PullUp);
    k_in[3]  = new DigitalIn(kd, PullUp);
    k_in[4]  = new DigitalIn(ke, PullUp);
    k_out[0] = new DigitalInOut(kx, PIN_OUTPUT, OpenDrain, 1);
    k_out[1] = new DigitalInOut(ky, PIN_OUTPUT, OpenDrain, 1);
    k_out[2] = new DigitalInOut(kz, PIN_OUTPUT, OpenDrain, 1);
    k_out[3] = new DigitalInOut(kw, PIN_OUTPUT, OpenDrain, 1);
    k_out[4] = new DigitalInOut(kv, PIN_OUTPUT, OpenDrain, 1);
    key_mode    = 25;
    key_in_num  = 5;
    key_out_num = 5;
    initialize();
}

void Keypad::initialize(void)
{
    uint8_t j,i;
    for (j = 0; j < key_out_num; j++) {
        for(i = 0; i < key_in_num; i++) {
            key_transent_cntr[j][i] = CHNG_CNT;
            key_state[j][i] = OFF_state;
        }
    }
    for(i = 0; i < BF_SIZE; i++) {
        buf[i] = 0;
    }
    read_addr = 0;
    write_addr = 0;
    tk.attach_us(callback(this, &Keypad::key_scan), 2000); // 2mS
}

void Keypad::key_scan(void)
{
    LEDON;
    for (int32_t j = 0; j < key_out_num; j++) {
        for (int32_t k = 0; k < key_out_num; k++) {
            *k_out[k] = 1;
        }
        *k_out[j] = 0;
        wait_us(1);
        for (int32_t i = 0; i < key_in_num; i++) {
            switch (key_state[j][i]) {
                case OFF_state:
                    if (*k_in[i] == 0) { // key on
                        key_state[j][i] = OFF_to_ON_transient;
                        key_transent_cntr[j][i] = CHNG_CNT;
                    }
                    break;
                case OFF_to_ON_transient:
                    if (*k_in[i] == 0) { // key on
                        if (--key_transent_cntr[j][i] < -CHNG_CNT) {
                            // save data into buffer
                            bf_put(j * key_in_num + i + 1);
                            key_state[j][i] = ON_state;
                        }
                    } else {    // key off
                        if (++key_transent_cntr[j][i] > CHNG_CNT) {
                            key_state[j][i] = OFF_state;
                        }
                    }
                    break;
                case ON_state:
                    if (*k_in[i] == 1) { // key off
                        key_state[j][i] = ON_to_OFF_transient;
                        key_transent_cntr[j][i] = -CHNG_CNT;
                    }
                    break;
                case ON_to_OFF_transient:
                    if (*k_in[i] == 0) { // key on
                        if (--key_transent_cntr[j][i] < -CHNG_CNT) {
                            key_state[j][i] = ON_state;
                        }
                    } else {    // key off
                        if (++key_transent_cntr[j][i] > CHNG_CNT) {
                            key_state[j][i] = OFF_state;
                        }
                    }
                    break;
                default:    // just in case
                    key_state[j][i] = OFF_state;
                    break;
            }
        }
    }
    for (int32_t k = 0; k < key_out_num; k++) {
        *k_out[k] = 1;
    }
    LEDOFF;
}

uint8_t Keypad::read(void)
{
    return bf_get();
}

bool Keypad::read_state(uint8_t key_num)
{
    
    uint8_t x = (key_num - 1) % key_out_num;
    uint8_t y = (key_num - 1)/ key_out_num;
    if (key_state[y][x] == ON_state) {
        return true;
    } else {
        return false;
    }
}

void Keypad::bf_put(char dt)
{
    uint8_t next = write_addr + 1;
    if (next == BF_SIZE) {
        next = 0;
    }
    buf[write_addr] = dt;
    write_addr = next;
}

int8_t Keypad::bf_get (void)
{
    if (read_addr == write_addr) {
        return 0;
    }
    uint8_t dt = buf[read_addr];
    ++read_addr;
    if (read_addr == BF_SIZE) {
        read_addr = 0;
    }
    return dt;
}