rt-thread-official/bsp/x1000/drivers/board_key.c

306 lines
7.5 KiB
C
Raw Normal View History

2017-11-11 13:51:56 +08:00
/*
* File : drv_gpio_keyboard.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2015-11-19 Urey the first version
*/
/*********************************************************************************************************
** Include Files
*********************************************************************************************************/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_gpio.h"
#include "board_key.h"
#ifdef RT_USING_AUDIO_PLAYER
#include <player_app.h>
#endif
#define KEY_DEBUG
#ifdef KEY_DEBUG
#define KEY_DBG(...) rt_kprintf("[KEY]"),rt_kprintf(__VA_ARGS__)
#else
#define KEY_DBG(...)
#endif
static keyboard_event_handler_t _handler = RT_NULL;
#if defined(BOARD_HALLEY2)
/* 4 keys
* SW1 SW2 SW3 SW5
* Vol- Vol+ Play/Pause Mode/Config
* PA10 PA11 PB28 PB31
*/
static struct keyboard_io_def keyboard_io_tbl[] =
{
//Vol-/Next Song
{
GPIO_PORT_A, GPIO_Pin_10 ,
KEY_NEXT, KEY_VOLDEC,
},
//Vol+/Prev Song
{
GPIO_PORT_A, GPIO_Pin_11 ,
KEY_PREV, KEY_VOLINC,
},
//Play_Pause
{
GPIO_PORT_B, GPIO_Pin_28 ,
KEY_UNKNOWN, KEY_PLAY_PAUSE,
},
//Mode/Config
{
GPIO_PORT_B, GPIO_Pin_31,
KEY_CONFIG, KEY_NETWORK_MODE,
},
};
#elif defined(BOARD_HALLEY2_REALBOARD)
/* 6 keys
* 11 12 21 22 31 32
* ON/OFF MODE V+ V- BT/MUTE WIFI
*/
static struct keyboard_io_def keyboard_io_tbl[] =
{
//ON/OFF
{
GPIO_PORT_B, GPIO_Pin_31,
KEY_UNKNOWN, KEY_PWROFF,
},
//V+
{
GPIO_PORT_B, GPIO_Pin_25,
KEY_UNKNOWN, KEY_VOLINC,
},
//V-
{
GPIO_PORT_B, GPIO_Pin_2,
KEY_UNKNOWN, KEY_VOLDEC,
},
//BT/MUTE
{
GPIO_PORT_B, GPIO_Pin_3,
KEY_SOURCE, KEY_MUTE,
},
//WIFI
{
GPIO_PORT_B, GPIO_Pin_28,
KEY_UNKNOWN, KEY_CONFIG,
},
};
#elif defined(BOARD_HALLEY2_REALBOARD_V2)
struct keyboard_io_def keyboard_io_tbl[] =
{
//ON/OFF
{
GPIO_PORT_D, GPIO_Pin_0,
KEY_UNKNOWN, KEY_UNKNOWN,
},
//V+
{
GPIO_PORT_B, GPIO_Pin_28,
KEY_UNKNOWN, KEY_UNKNOWN,
},
//V-
{
GPIO_PORT_B, GPIO_Pin_31,
KEY_UNKNOWN, KEY_UNKNOWN,
},
//WIFI config
{
GPIO_PORT_D, GPIO_Pin_2,
KEY_UNKNOWN, KEY_UNKNOWN,
},
};
#else
struct keyboard_io_def keyboard_io_tbl[] =
{
//PWRKEY KEY
{
GPIO_PORT_B, GPIO_Pin_31,
KEY_UNKNOWN, KEY_UNKNOWN
},
};
#endif
#define CFG_MAX_KEY_NBR sizeof(keyboard_io_tbl)/sizeof(keyboard_io_tbl[0])
static struct rt_mailbox* _keyMb = RT_NULL;
void keyboard_irq_callback(void *param)
{
KEY_DBG("%d\n", (int)param);
if (_keyMb)
{
struct keyboard_io_def* key;
int value = (int)param;
key = &keyboard_io_tbl[value];
if(rt_mb_send(_keyMb, (rt_uint32_t)param) == RT_EOK)
gpio_mask_irq(key->port, key->pin);
}
}
#define KEY_EVENT_DOWN 0x01
#define KEY_EVENT_HOLD 0x02
#define KEY_EVENT_UP 0x04
#define KEY_SCAN_STEP_TIME 10
#define KEY_SCAN_HOLD_THRESHOLD 2000
//Scan the single key
rt_uint8_t key_scan(struct keyboard_io_def *keyIO)
{
static rt_uint8_t keyTrigger = 0;
static rt_uint8_t keyRelease = 0;
static rt_uint8_t keyHold = 0;
rt_uint8_t keyValue = 0;
//elimination buffeting
do
{
keyValue = gpio_get_value(keyIO->port,keyIO->pin);
rt_thread_delay(rt_tick_from_millisecond(KEY_SCAN_STEP_TIME));
}while(keyValue != gpio_get_value(keyIO->port,keyIO->pin));
keyValue ^= 0x01;
keyTrigger = keyValue &(keyValue ^ keyHold);
keyRelease = (keyValue ^ keyTrigger ^ keyHold);
keyHold = keyValue;
// KEY_DBG("keyValue = %x\n,keyTrigger = %x\n,keyRelese = %x\n,keyHold = %x\n",keyValue,keyTrigger,keyRelease,keyHold);
if(keyTrigger != 0)
return KEY_EVENT_DOWN;
else if(keyHold != 0)
return KEY_EVENT_HOLD;
return KEY_EVENT_UP;
}
void kbd_thread(void* parameter)
{
int keyId;
rt_uint8_t keyEvent;
rt_uint8_t keyValue;
rt_uint32_t keyHoldTime;
_keyMb = rt_mb_create("key", 4, RT_IPC_FLAG_FIFO);
while (1)
{
if(rt_mb_recv(_keyMb, (rt_uint32_t*)&keyId, RT_TICK_PER_SECOND) != RT_EOK)
{
//if no key pressed,check power key...
keyId = 0;
}
{
struct keyboard_io_def* key;
// Check key ID
if(keyId >= CFG_MAX_KEY_NBR)
{
rt_kprintf("keyID error\n");
continue;
}
key = &keyboard_io_tbl[keyId];
keyEvent = key_scan(key);
/* No key input */
if(keyEvent == KEY_EVENT_UP)
{
gpio_unmask_irq(key->port, key->pin);
continue;
}
KEY_DBG("key %d down\n", keyId);
//Wait for key RELEASE
keyHoldTime = 0;
do
{
keyEvent = key_scan(key);
if(keyEvent == KEY_EVENT_HOLD)
{
keyHoldTime += KEY_SCAN_STEP_TIME;
if(keyHoldTime > KEY_SCAN_HOLD_THRESHOLD)
break;
}
} while (keyEvent != KEY_EVENT_UP);
KEY_DBG("key %d up,hold time = %dms\n", keyId,keyHoldTime);
if(keyHoldTime > KEY_SCAN_HOLD_THRESHOLD)
keyValue = key->longKey;
else
keyValue = key->shortKey;
//send key event
if (_handler) _handler(EVENT_KEY_DOWN | keyValue);
//Wait for KEYUP
while (keyEvent != KEY_EVENT_UP)
{
keyEvent = key_scan(key);
rt_thread_delay(RT_TICK_PER_SECOND / 10);
}
if (_handler) _handler(EVENT_KEY_UP | keyValue);
gpio_unmask_irq(key->port, key->pin);
}
}
}
void rt_hw_keyboard_set_handler(keyboard_event_handler_t handler)
{
_handler = handler;
}
void rt_hw_keyboard_init(void)
{
int i;
rt_thread_t tid;
tid = rt_thread_create("key", kbd_thread, RT_NULL, 2048, 16, 10);
if (tid)
rt_thread_startup(tid);
/* initialize all IO for keyboard */
for (i = 0; i < CFG_MAX_KEY_NBR; ++i)
{
gpio_set_func(keyboard_io_tbl[i].port,keyboard_io_tbl[i].pin,GPIO_INPUT_PULL | GPIO_INT_FE);
gpio_set_irq_callback(keyboard_io_tbl[i].port,keyboard_io_tbl[i].pin,keyboard_irq_callback, (void*)i);
gpio_unmask_irq(keyboard_io_tbl[i].port,keyboard_io_tbl[i].pin);
}
}