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:
2017-09-30
Revision:
0:b7249629f337
Child:
1:ed0ad90ad734

File content as of revision 0:b7249629f337:

/*
 * Mbed Library / Akizuki AE-KIT45-KEYPAD4X3
 *  http://akizukidenshi.com/catalog/g/gK-12229/
 *
 * Copyright (c) 2017 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created:    September 27th, 2017
 *      Revised:    October    1st, 2017
 */

#include "Keypad.h"

extern Serial pc;
extern DigitalOut my_led;

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 DigitalOut (kx);
    k_out[1] = new DigitalOut (ky);
    k_out[2] = new DigitalOut (kz);
    *k_out[0] = 1;
    *k_out[1] = 1;
    *k_out[2] = 1;
    uint8_t j,i;
    for (j = 0; j < 3; j++){
        for(i = 0; i < 4; i++){
            key_transent_cntr[j][i] = CHNG_CNT;
            key_state[j][i] = Off_state;
        }
    }
    for(i = 0; i < 32; 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)
{
    //my_led = 1;
    for (int32_t j = 0; j < 3; j++){
        *k_out[0] = 1;   *k_out[1] = 1;  *k_out[2] = 1;
        *k_out[j] = 0;
        wait_us(1);
        for (int32_t i = 0; i < 4; i++){
            switch (key_state[j][i]){
                case Off_state:
                    //my_led = 1;
                    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:
                    //my_led = 1;
                    if (*k_in[i] == 0){ // key on
                        if (--key_transent_cntr[j][i] < -CHNG_CNT){
                            //my_led = 1;
                            bf_put(j * 4 + i + 1); // save data into buffer
                            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:
                    //my_led = 1;
                    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:
                    //my_led = 1;
                    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;
            }
            //my_led = 0;
        }
    }
    *k_out[0] = 1;   *k_out[1] = 1;  *k_out[2] = 1;
    //my_led = 0;
}

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

#define BF_SIZE 16

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