请保留-> 【原文: https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】
YIE001上有两个拨动开关,可通过对应的寄存器位得知它们的状态,以实现交互控制。这篇尝试将按键获取,以及图形显示的编码。
1 获取拨动开关状态
UEFI开发探索第75篇中,列出了YIE001开发板的硬件资源。板子上提供了两个拨动开关,分别对应CH366的GPI1和GPI2。
对照CH366的芯片手册,定义其相关的宏定义:
#define CH366GPIR 0x02
#define KEY1 1 //GPI1 -- GPIR(IO基地址+02h) bit 1
#define KEY2 2 //GPI2 -- GPIR(IO基地址+02h) bit 2
在开发板YIE001上,拨动开关拨下(也即靠近PCIE槽的方向),对应的寄存器位值为0;拨上后对应的寄存器值为1。实现代码如下:
/**
获取开发板YIE001上拨动开关的状态.
@param IoBaseAddress YIE001上PCIE芯片的基地址
@param KeyNum 拨动开关的标识,Key1和Key2
@retval 1 拨下(靠近PCIE插槽)
0 拨上
**/
UINT8 GetYIE001Key(UINT16 IoBaseAddress,UINT8 KeyNum)
{
UINT8 regValue=0;
regValue = IoRead8(MyIoBaseAddr+CH366GPIR); //GPIR
if(KeyNum == KEY1)
regValue &=0x02;
if(KeyNum == KEY2)
regValue &=0x04;
if(regValue)
return 1;
else
return 0;
}
2 显示开关状态
为了显示拨动开关的状态,复用了上一篇博客中的代码。本篇博客的示例工程为YIE1Key,结合了访问YIE001开发板和图形显示的代码。
看代码比较容易明白实现的功能:
VOID HelloMyROM(VOID)
{
EFI_INPUT_KEY key={0,0};
UINT64 flag;
UINT8 *s_text1 = "欢迎进入UEFI的世界!";
UINT8 *s_text2 = "按'ESC'键或'1'退出此界面";
UINT8 *s_key1str1 = "拨动开关1拨下!";
UINT8 *s_key1str2 = "拨动开关1拨上!";
UINT8 *s_key2str1 = "拨动开关2拨下!";
UINT8 *s_key2str2 = "拨动开关2拨上!";
UINT8 tempKey1;
UINT8 tempKey2;
//图形显示测试
flag = InintGloabalProtocols(GRAPHICS_OUTPUT);
Print(L"flag=%x\n",flag);
SwitchGraphicsMode(TRUE);
SetBKG(&(gColorTable[DEEPBLUE]));
draw_string(s_text1, 120, 100, &MyFontArray, &(gColorTable[YELLOW]));
draw_string(s_text2, 120, 140, &MyFontArray, &(gColorTable[YELLOW]));
tempKey1 = GetYIE001Key(MyIoBaseAddr,KEY1);
tempKey2 = GetYIE001Key(MyIoBaseAddr,KEY2);
if(tempKey1)
draw_string(s_key1str1, 120, 200, &MyFontArray, &(gColorTable[WHITE]));
else
draw_string(s_key1str2, 120, 200, &MyFontArray, &(gColorTable[WHITE]));
if(tempKey2)
draw_string(s_key2str1, 120, 230, &MyFontArray, &(gColorTable[WHITE]));
else
draw_string(s_key2str2, 120, 230, &MyFontArray, &(gColorTable[WHITE]));
while(key.ScanCode!=0x17) //ESC
{
GetKey(&key);
if(key.UnicodeChar == 0x31)
break;
if(GetYIE001Key(MyIoBaseAddr,KEY1)!=tempKey1)
{
if(tempKey1)
{
tempKey1 = 0;
draw_string(s_key1str1, 120, 200, &MyFontArray, &(gColorTable[DEEPBLUE])); //消除显示
draw_string(s_key1str2, 120, 200, &MyFontArray, &(gColorTable[WHITE]));
SetLed(MyIoBaseAddr,LED1,LEDON);
}
else
{
tempKey1 = 1;
draw_string(s_key1str2, 120, 200, &MyFontArray, &(gColorTable[DEEPBLUE])); //消除显示
draw_string(s_key1str1, 120, 200, &MyFontArray, &(gColorTable[WHITE]));
SetLed(MyIoBaseAddr,LED1,LEDOFF);
}
Delayms(200);
}
if(GetYIE001Key(MyIoBaseAddr,KEY2)!=tempKey2)
{
if(tempKey2)
{
tempKey2 = 0;
draw_string(s_key2str1, 120, 230, &MyFontArray, &(gColorTable[DEEPBLUE])); //消除显示
draw_string(s_key2str2, 120, 230, &MyFontArray, &(gColorTable[WHITE]));
SetLed(MyIoBaseAddr,LED2,LEDON);
}
else
{
tempKey2 = 1;
draw_string(s_key2str2, 120, 230, &MyFontArray, &(gColorTable[DEEPBLUE])); //消除显示
draw_string(s_key2str1, 120, 230, &MyFontArray, &(gColorTable[WHITE]));
SetLed(MyIoBaseAddr,LED2,LEDOFF);
}
Delayms(200);
}
}
SetMyMode(OldGraphicsMode);
SwitchGraphicsMode(FALSE);
}
修改了框架代码中的HelloMyROM()函数,主要的功能如下:
(1) 初始化图形显示,并在屏幕上打印相应的提示字符串;
(2) 进入按键获取的循环,只有接收到用户按’ESC’或’1’,才会退出循环;
(3) 获取拨动开关状态,更新拨动开关状态的显示。
3 测试
编译命令如下:
C:\UEFIWorkspace>build -t VS2015x86 -p RobinPkg\RobinPkg.dsc -m RobinPkg\Drivers\YIE1Key\YIE1Key.inf -a X6
Option ROM的界面显示如图1所示。
拨动相应的开关后,界面会显示目前的拨动开关状态。结合YIE001的这种拨动开关交互机制,可以试着实现更丰富的有趣效果。
Gitee地址:https://gitee.com/luobing4365/uefi-explorer
项目所用ROM文件位于:/ 77 YIE1Key下
1,376 total views, 2 views today