⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 2 页
字号:
//----------------------------------------------------
//Copyright (C), 2004-2009,  lst.
//版权所有 (C), 2004-2009,   lst.
//所属模块:键盘
//作者:lst
//版本:V1.1.0
//文件描述: 提供键盘设备管理功能的公共部分,移植需要修改的见key_xxx.c文件
//其他说明:
//修订历史:
//    2. 日期:20090131
//       作者:lst
//       新版本号:v1.1.0
//       修改说明:
//          1.把硬件相关的函数key_scan_hard移到key_xxx.c中.
//          2.增加key_read函数和key_read_direct函数
//    1. 日期:20090104
//       作者:lst
//       新版本号:v1.0.0
//       修改说明:原始版本
//------------------------------------------------------
#include "inc_os.h"
#include "key.h"
static struct key_script  tg_key_buf[cn_key_buf_len];
static struct ring_buf tg_key_queue;
static struct  pan_device *pg_key_dev;
static struct  dev_handle *pg_key_rhdl;
static struct  dev_handle *pg_key_lhdl;
static uint16_t u16g_evtt_key;
static struct semaphore_LCB *pg_key_semp;

//建立这样的表是必要的,可以使应用程序摆脱对特定硬件的依赖
//PC键盘扫描码是广泛使用的,就以PC键盘为基准吧.本表现在是随便填充,应用时应该改
//为与实际键盘定义对应。
uint16_t u16g_key_table[] =
{
    0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
    0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
    0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
    0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
    0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
    0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
    0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
};

//----初始化按键设备----------------------------------------------------------
//功能: 初始化键盘模块,包括:创建键盘根设备;创建键盘信号量;登记键盘扫描事件
//      类型;pop键盘扫描事件以启动扫描(实际扫描工作要等多线程启动后才开始)
//参数: 无
//返回: true=成功初始化,false=初始化失败,一般是资源(内存)不足引起
//----------------------------------------------------------------------------
bool_t module_init_keyboard(void)
{
    ring_init(&tg_key_queue,(uint8_t*)tg_key_buf,
                        sizeof(struct key_script)*cn_key_buf_len);
    //以下建立key设备,该设备支持左手读、右手写和公共控制操作
    //设备并无信号量保护,也就是说,键盘设备允许无穷多重并发访问。
    //但是,按键缓冲区被信号量pg_key_semp保护,如果发生并发访问且缓冲区中没有按
    //键,则部分访问的线程将按优先级在该信号量的同步队列中等候。
    pg_key_dev = dev_add_root_device("key",
                                     NULL,NULL,      //无信号量保护
                                     (dev_write_func) key_right_write ,
                                     (dev_read_func ) NULL_func,
                                     (dev_ctrl_func ) key_ctrl ,
                                     (dev_write_func ) NULL_func ,
                                     (dev_read_func  ) key_left_read ,
                                     (dev_ctrl_func  ) key_ctrl
                                     );    //"key"是一个根设备
    if(pg_key_dev == NULL)
        goto exit_from_add_dev;
    pg_key_semp = semp_create(cn_key_buf_len,0,"read_key");
    if(pg_key_semp == NULL)
        goto exit_from_semp;
    //tg_key_queue是key设备私有数据
    pg_key_dev->private_tag     = (ptu32_t)(&tg_key_queue);
    pg_key_rhdl = dev_open_right("key",0);
    if(pg_key_rhdl == NULL)
        goto exit_from_rhdl;
    pg_key_lhdl = dev_open_left("key",0);
    if(pg_key_lhdl == NULL)
        goto exit_from_lhdl;
    //无需判断y_evtt_regist函数的返回值,如果返回false,那么随后的y_event_pop也
    //会返回false,可以一并判断。
    u16g_evtt_key = y_evtt_regist(true,false,cn_prio_RRS,10,key_scan,512,NULL);
    if(u16g_evtt_key == cn_invalid_evtt_id)
        goto exit_from_regist;
    if(y_event_pop(u16g_evtt_key,0,0,0) == (uint16_t)cn_invalid_event_id)
    {
        goto exit_from_pop;
    }
    return true;
    
exit_from_pop:
    y_evtt_unregist(u16g_evtt_key);
exit_from_regist:
exit_from_lhdl:
exit_from_rhdl:
    semp_delete(pg_key_semp);
exit_from_semp:
    dev_delete_device(pg_key_dev);
exit_from_add_dev:
    return false;
}

//----右手写键盘--------------------------------------------------------------
//功能: 往按键队列中写入一个按键
//参数: key_rhdl,键盘右手设备指针
//      pt_key,键值,struct key_script *指针
//      其他参数: dev_write系统调用的填充物
//返回: 成功写入的按键数量(0或1)
//----------------------------------------------------------------------------
ptu32_t key_right_write(struct  dev_handle *key_rhdl,ptu32_t pt_key,
                                ptu32_t  res1,ptu32_t res2)
{
    uint16_t len;
    if((struct key_script *)pt_key == NULL)
        return 0;
    int_save_asyn_signal();
    //把按键写入键盘设备的按键缓冲区中,读出时按原样读出,故无需考虑字节序和
    //对齐问题。
    len = ring_write(&tg_key_queue,(uint8_t *)pt_key,sizeof(struct key_script));
    if(len != 0)    //按键写入队列,缓冲区满会造成写不进去
    {
        //若有事件在等待,则唤醒。若有多个事件在等待队列中,唤醒优先级最高的,而
        //不是最先挂起的。多个线程共享键盘输入时,就有可能出现多个事件同时挂起
        //在按键信号量队列中的情况。
        semp_post(pg_key_semp);
    }
    int_restore_asyn_signal();
    return 1;
}

//----左手读键盘--------------------------------------------------------------
//功能: 从按键队列中读取一个按键
//参数: key_lhdl,按键的左手操作指针
//      pt_key,保存键值的指针,转成struct key_script *类型访问
//      mode,读模式,cn_key_mode_sch=无按键则阻塞,1=不阻塞,直接返回.
//      timeout,当mode==cn_key_mode_sch时,timeout设定等待超时时间,毫秒数,
//      将被向上取整为cn_tick_ms的整数倍。
//返回:
//----------------------------------------------------------------------------
ptu32_t key_left_read(struct  dev_handle *key_lhdl,ptu32_t pt_key,
                                ptu32_t  mode,ptu32_t timeout)
{
    uint16_t len;
    if((uint8_t *)pt_key == NULL)
        return 0;
    int_save_asyn_signal();
re_read_key:
    //从键盘设备的按键缓冲区中读一个按键,有按键则返回sizeof(struct key_script)
    //无按键返回0
    len = ring_read(&tg_key_queue,(uint8_t *)pt_key,sizeof(struct key_script));
    if(len == 0)        //队列中没有按键
    {
        if(mode == cn_key_mode_sch)
        {
            int_restore_asyn_signal();  //阻塞前必须开中断,否则会死掉
            if(semp_pend(pg_key_semp,timeout))   //进入等待队列
                goto re_read_key;       //取得信号量返回,再次读按键
            else
                ;                       //超时返回,退出
        }
    }
    int_restore_asyn_signal();
    return (len!=0);
}

//----键盘设备控制------------------------------------------------------------
//功能:
//参数:
//返回:
//----------------------------------------------------------------------------
ptu32_t key_ctrl(struct  dev_handle *key_devio,uint32_t cmd,
                    ptu32_t res1,ptu32_t res2)
{
    return 0;
}

//----键盘扫描任务-------------------------------------------------------------
//功能: 周期性地调用硬件扫描程序,获取用户敲击信息,合成标准键盘码,从右手写入
//      键盘设备。键盘码按照PS/2标准扫描码。扫描码有两种不同的类型:通码
//      (make code)和断码(break code)。当一个键被按下或持续按住时,就产生一个通
//      码;而当一个键被释放时,就产生一个断码。根据键盘按键扫描码的不同,可将按键
//      分为如下几类:
//      第一类键,通码为1字节,断码为0xF0+通码。如A键,通码为0x1C,断码为0xF0 0x1C。
//      第二类键,通码为2字节0xE0+0xXX形式,断码为0xE0+0xF0+0xXX形式。如right ctrl

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -