![]() |
#2
miaowangjian2010-05-30 09:55
code:console.h(新)
![]() //文件:console.h //功能:console头文件,控制台需要用到的公共函数的声明等 //作者:miao //时间:2010-5-30 //VGA #define CRTC_ADDR_REG 0x3D4 // CRT 控制寄存器 - 地址(索引)存器 #define CRTC_DATA_REG 0x3D5 // CRT 控制寄存器 - 数据(I/O)寄存器 #define CRTC_DATA_IDX_START_ADDR_H 0xC // 寄存器索引:显存使用的起始地址 (头) #define CRTC_DATA_IDX_START_ADDR_L 0xD // 寄存器索引:显存使用的起始地址 (尾) #define CRTC_DATA_IDX_CURSOR_H 0xE // 寄存器索引:光标位置 (头) #define CRTC_DATA_IDX_CURSOR_L 0xF // 寄存器索引:光标位置 (尾) #define V_MEM_BASE 0xB8000 // 显存在内存的起始地址 #define V_MEM_SIZE 0x8000 // 显存大小 = 32K = 0xbffff - 0xb8000 //颜色 #define BLACK 0x0 //0000:黑色 #define WHITE 0x7 //0111:白色 #define RED 0x4 //0100:红色 #define GREEN 0x2 //0010:绿色 #define BLUE 0x1 //0001:蓝色 #define FLASH 0x80 //1000 0000:闪烁 #define BRIGHT 0x08 //0000 1000:高亮 #define MAKE_COLOR(x,y) ((x<<4) | y) //MAKE_COLOR(背景颜色,字符颜色) // 使用MAKE_COLOR宏示例:MAKE_COLOR(BLUE, RED) //蓝底红字 // MAKE_COLOR(BLACK, RED) | BRIGHT //黑底红字+字体高亮 // MAKE_COLOR(BLACK, RED) | BRIGHT | FLASH //黑底红字+字体高亮+字体闪烁 // void printChar(char ch); // void printString(char * info); // asm void printColorString(char * info, int color); // void printNumber(int num); void OnLineUpFun(); struct on_s onLineUp = {"OnLineUp",&OnLineUpFun,NULL}; void OnLineDownFun(); struct on_s onLineDown = {"OnLineDown",&OnLineDownFun,NULL}; void OnPageUpFun(); struct on_s onPageUp = {"OnPageUp",&OnPageUpFun,NULL}; void OnPageDownFun(); struct on_s onPageDown = {"NullOn",&OnPageDownFun,NULL}; code:console.c(新) ![]() //文件:console.c //功能:控制台,管理CRT,设置窗口尺寸位置、前景色、背景色、光标等 //作者:miao //时间:2010-5-25 char lineNum=0; void SetLine() { asm{cli} out_byte(CRTC_ADDR_REG, CRTC_DATA_IDX_START_ADDR_H); out_byte(CRTC_DATA_REG, ((80*lineNum)>>8)&0xff); out_byte(CRTC_ADDR_REG, CRTC_DATA_IDX_START_ADDR_L); out_byte(CRTC_DATA_REG, ((80*lineNum))&0xff); asm{sti} } void OnLineDownFun() { lineNum++; if(lineNum>100) lineNum=100; SetLine(); InitKeyOnEvent(onLineDown,0x50); } void OnLineUpFun() { lineNum--; if(lineNum<0) lineNum=0; SetLine(); InitKeyOnEvent(onLineUp,0x48); } void OnPageDownFun() { lineNum+=25; if(lineNum>100) lineNum=100; SetLine(); InitKeyOnEvent(onPageDown,0x51); } void OnPageUpFun() { lineNum-=25; if(lineNum<0) lineNum=0; SetLine(); InitKeyOnEvent(onPageUp,0x49); } |
一个域,包含以下几个基本要素:
1.生命值
2.(主动)动作函数 //action 函数
3.(被动)动作函数 //on 事件(函数)
4.子域 //未实现
域结构的操作(相当于域结构的系统调用函数):
1.运行域结构 //yu.c 中的run()函数
(1)执行动作双向循环链表中的一个动作
(2)执行.(被动)动作函数(on事件)列表里的所有函数
(3)指向下一个(主动)动作
2.加载(主动)动作函数 //向动作双向循环链表添加一个动作,见yu.c 中的AddAction(struct action_s *newAction)函数
3.移除(主动)动作函数 //从动作双向循环链表移除一个动作,见yu.c 中的DelAction(struct action_s *delAction)函数
4.注册一个on 事件 //可重复性的向on事件列表添加函数(p.s:(主动)动作函数具有唯一性)
域结构运行特点:
动作周期:执行一遍run()函数,形成一个动作周期,在这个过程里,只有一个(主动)动作和以及执行此周期前的所有on 事件被执行,在此过程中,向on事件列表添加的函数,会在下一个动作周期执行。
域周期:动作双向循环链表中所有的(主动)动作都被执行了一遍,形成一个域周期,在一个域周期内一个(主动)动作最多执行一遍,若在一个域周期内添加了新的(主动)动作,将会在周期结束时,或者说下各个域周期开始时被执行(若没有在此域周期内又被移除掉的话

之所以要花费精力来将“域”的情况进行如上总结,是因为我以后将会完全利用域结构来实现这个操作系统,若不理解域的特性,就无法理解程序的内在逻辑。
此次实现键盘驱动,我将键盘的字符输入功能和键盘作为控制器的控制功能分离开来,利用域结构的结构特点分别实现。主要实现的是将所有可显示字符的提取部分,控制部分,根据当前需要简单实现了几个。其他的控制功能,可以随时随意的添加,而不会对以实现部分有什么影响。
为了便于理解,先使用“域语言”伪代码描述一遍:

键盘域:
数据:
生命值:int kb_life = 0;
shift状态:t_bool shift;
CapsLock状态:t_bool capsLock;
NumLock状态:t_bool numLock;
0xE0扫描码:t_bool on0xE0Flag;
0xE1扫描码:t_bool on0xE1Flag;
键码双缓冲池:struct keyBuf_s keyBuf[2];等…… //为了减少对键盘中断的影响,建立了一个双缓冲池结构,轮流提供给键盘中断保存键码
键码字符映射表:t_32 keymap[NR_SCAN_CODES * 2];//用于将扫描码转换为相应字符
按键动作映射表:struct on_s *keyOntable[0x100];//用于动态实现某个按钮的控制性功能
主动函数:
键码转字符:void ScanCodeToCharFun(); //读取键码缓冲池里的扫描码,提取与转换成对应的字符
{
交换键码双缓冲池,若缓冲池中无记录,退出函数。
循环提取缓冲池中的扫描码:
从缓冲池取得扫描码。
若按下shift,从键码字符映射表的第二列中获取对应的字符,否则从第一列获取。
若CapsLock键被按下且是字母,将大小写互换,
(否则)若扫描码是小键盘区的且NumLock键按下,重新获取在第二列中获取对应的字符。
若获取的字符值为零,跳入下一循环。
已经取得字符了,根据需要处理吧,这里就简单打印出来。
}
被动函数:
键盘中断处理:void OnKeyEvent(); //这个是一个特殊的(被动)动作函数,它是由操作系统外部中断调用,与域的on事件区别在于,在任何时候都有可能发生,所以要编写得尽可能简练。
{
取得扫描码。
根据扫描码,查找按键动作映射表中对应的被动函数,注册到on事件列表上。
若键码转字符动作被禁止,或是中断码,不进行进一步处理,退出函数
若缓冲池未满,将扫描码记录到缓冲池
}
Shift按下:void OnShiftDownFun();
{
标记Shift被按下,注册自身Shift松开
}
Shift松开:void OnShiftUpFun()
{
标记Shift松开,注册Shift按下
}
CapsLock点击:void OnCapsLockFun()
{
置反CapsLock状态值,重新注册自身
}
NumLock点击:void OnNumLockFun()
{
置反NumLock状态值,重新注册自身
}
……
……
当键码转字符执行时,生命值长,若生命值过大,生命值归零,注销键码转字符动作。
当生命值为零时,若键盘中断处理执行时,加载键码转字符动作,生命值设为一。
数据:
生命值:int kb_life = 0;
shift状态:t_bool shift;
CapsLock状态:t_bool capsLock;
NumLock状态:t_bool numLock;
0xE0扫描码:t_bool on0xE0Flag;
0xE1扫描码:t_bool on0xE1Flag;
键码双缓冲池:struct keyBuf_s keyBuf[2];等…… //为了减少对键盘中断的影响,建立了一个双缓冲池结构,轮流提供给键盘中断保存键码
键码字符映射表:t_32 keymap[NR_SCAN_CODES * 2];//用于将扫描码转换为相应字符
按键动作映射表:struct on_s *keyOntable[0x100];//用于动态实现某个按钮的控制性功能
主动函数:
键码转字符:void ScanCodeToCharFun(); //读取键码缓冲池里的扫描码,提取与转换成对应的字符
{
交换键码双缓冲池,若缓冲池中无记录,退出函数。
循环提取缓冲池中的扫描码:
从缓冲池取得扫描码。
若按下shift,从键码字符映射表的第二列中获取对应的字符,否则从第一列获取。
若CapsLock键被按下且是字母,将大小写互换,
(否则)若扫描码是小键盘区的且NumLock键按下,重新获取在第二列中获取对应的字符。
若获取的字符值为零,跳入下一循环。
已经取得字符了,根据需要处理吧,这里就简单打印出来。
}
被动函数:
键盘中断处理:void OnKeyEvent(); //这个是一个特殊的(被动)动作函数,它是由操作系统外部中断调用,与域的on事件区别在于,在任何时候都有可能发生,所以要编写得尽可能简练。
{
取得扫描码。
根据扫描码,查找按键动作映射表中对应的被动函数,注册到on事件列表上。
若键码转字符动作被禁止,或是中断码,不进行进一步处理,退出函数
若缓冲池未满,将扫描码记录到缓冲池
}
Shift按下:void OnShiftDownFun();
{
标记Shift被按下,注册自身Shift松开
}
Shift松开:void OnShiftUpFun()
{
标记Shift松开,注册Shift按下
}
CapsLock点击:void OnCapsLockFun()
{
置反CapsLock状态值,重新注册自身
}
NumLock点击:void OnNumLockFun()
{
置反NumLock状态值,重新注册自身
}
……
……
当键码转字符执行时,生命值长,若生命值过大,生命值归零,注销键码转字符动作。
当生命值为零时,若键盘中断处理执行时,加载键码转字符动作,生命值设为一。
除了键盘驱动程序以外,此次,还对显示器(视频)的端口进行了简单的操控,实现上下移动显示区域,以防止屏幕显示超出时,看不到新新的显示内容。
在下一步里,将进一步完善它,并争取实现一个简单的tty。
下面是此次新添加或有过修改的代码。
在print.c中添加了一个换行函数,函数代码如下

void disp_next()//换行
{
asm{
mov eax, disp_pos //求出下一行起始位置坐标
mov bl, 160
div bl
and eax, 0FFh
inc eax
mov bl, 160
mul bl
mov disp_pos, eax
}
}
{
asm{
mov eax, disp_pos //求出下一行起始位置坐标
mov bl, 160
div bl
and eax, 0FFh
inc eax
mov bl, 160
mul bl
mov disp_pos, eax
}
}
code:kernel.c(改)

//文件:kernel.c
//功能:内核程序,先初始化各个模块驱动,然后循环调用域执行函数,运行域结构
//运行:run.exe自动会编译boot.c与生成img并调用Bochs运行此程序。
//作者:miao
//时间:2010-5-30
#define YCBIT 32 //告诉编译器,以32位格式编译程序
#define YCORG 0x0 //此值会对在编译时对变量函数等产生地址基址偏移量,简单起便,设置为0
#include "global.h"
#include "kernel.h"
#include "print.h"
#include "klib.h"
#include "i8259.h"
#include "yu.h"
#include "console.h"//要在keyboard.h之前,因为keyboard.h里用到了console.h的一些变量
#include "keyboard.h"
void init();
//内核入口点
asm void main()
{
lgdt cs:GdtPtr //加载新的GDTR
mov eax, SelectorVideo
mov gs, ax //视频段选择子(目的)
mov eax, SelectorData32 //令32位代码段的变量(printPlace)可以读写
mov ds, ax
call init //初始化函数
sti //开中断
jmp kernel_main
}
void init()
{
disp_str("================ init start =================\n");
disp_str(" init idt -------------------------------- ");
init_prot(); //初始化IDT
disp_str("ok\n");
disp_str(" init keyboard --------------------------- ");
init_keyboard();//初始化键盘
disp_str("ok\n");
disp_str(" init yu\n");
life = 100;//初始化根域生命值
disp_str("----- init action ------------------------ ");
AddAction(&nullAction);//测试action函数用,模拟光标的功能
disp_str("ok\n");
disp_str("----- init on ---------------------------- ");
on_list.idx = 0;
on_list.total = 0;
on_list.flag = 1;
AddOn(&nullOn2);//测试on事件用,打印一个等边三角形
disp_str("ok\n");
disp_str("================ init end ===================\n");
}
int kernel_main()
{
while(life)
{
Run();
}
disp_str("================ yu end =====================\n");
disp_str("died");
while(1);
return 0;
}
#include "print.c"
#include "klib.c"
#include "i8259.c"
#include "yu.c"
#include "keyboard.c"
#include "console.c"
//功能:内核程序,先初始化各个模块驱动,然后循环调用域执行函数,运行域结构
//运行:run.exe自动会编译boot.c与生成img并调用Bochs运行此程序。
//作者:miao
//时间:2010-5-30
#define YCBIT 32 //告诉编译器,以32位格式编译程序
#define YCORG 0x0 //此值会对在编译时对变量函数等产生地址基址偏移量,简单起便,设置为0
#include "global.h"
#include "kernel.h"
#include "print.h"
#include "klib.h"
#include "i8259.h"
#include "yu.h"
#include "console.h"//要在keyboard.h之前,因为keyboard.h里用到了console.h的一些变量
#include "keyboard.h"
void init();
//内核入口点
asm void main()
{
lgdt cs:GdtPtr //加载新的GDTR
mov eax, SelectorVideo
mov gs, ax //视频段选择子(目的)
mov eax, SelectorData32 //令32位代码段的变量(printPlace)可以读写
mov ds, ax
call init //初始化函数
sti //开中断
jmp kernel_main
}
void init()
{
disp_str("================ init start =================\n");
disp_str(" init idt -------------------------------- ");
init_prot(); //初始化IDT
disp_str("ok\n");
disp_str(" init keyboard --------------------------- ");
init_keyboard();//初始化键盘
disp_str("ok\n");
disp_str(" init yu\n");
life = 100;//初始化根域生命值
disp_str("----- init action ------------------------ ");
AddAction(&nullAction);//测试action函数用,模拟光标的功能
disp_str("ok\n");
disp_str("----- init on ---------------------------- ");
on_list.idx = 0;
on_list.total = 0;
on_list.flag = 1;
AddOn(&nullOn2);//测试on事件用,打印一个等边三角形
disp_str("ok\n");
disp_str("================ init end ===================\n");
}
int kernel_main()
{
while(life)
{
Run();
}
disp_str("================ yu end =====================\n");
disp_str("died");
while(1);
return 0;
}
#include "print.c"
#include "klib.c"
#include "i8259.c"
#include "yu.c"
#include "keyboard.c"
#include "console.c"
code:yu.h(改)

//文件:yu.h
//功能:yu头文件,域结构需要用到的公共函数的声明等
//作者:miao
//时间:2010-5-30
#define NULL 0
#define NAME_MAX 32
typedef void (*action_fun)();
typedef void (*on_fun)();
//根域生命值(为零,退出域动作链表循环)
int life = 0;
//动作结构
struct action_s
{
char name[NAME_MAX]; //动作名称
action_fun run; //动作调用的函数
struct action_s *last; //上一动作
struct action_s *next; //下一动作
};
//动作链表
struct actionList_s
{
unsigned int count; //动作计数器
struct action_s *seek; //当前动作
}actionList = {0,NULL};
//添加一个动作到动作链表表里
void AddAction(struct action_s *newAction);
//从动作链表里删除一个动作
void DelAction(struct action_s *delAction);
void Run(); //执行当前动作
void NullActionFun();//空动作,限制链表执行速度或将来用于管理动作链表
struct action_s nullAction = {"NullFun",&NullActionFun,NULL,NULL};
//on事件结构
struct on_s
{
char name[NAME_MAX]; //on事件名称
on_fun run; //on调用的函数
struct on_s *next; //下一个on事件,暂时没有特别用处
char state; //保留,暂时没有特别用处
};
#define ON_LIST_MAX 100
//on事件表结构,双向向内增长堆栈
struct on_list_s
{
struct on_s *list[ON_LIST_MAX]; //on事件堆栈(on事件可以重复)
int idx; //指向lish空的地方
int total; //堆栈中on事件的总数
t_bool flag; //增长标记
}on_list;
//添加一个on事件到on队列(在on队列中on事件可重复添加)
void AddOn(struct on_s *newOn);
void NullOnFun1();//空on事件1
struct on_s nullOn1 = {"NullOn1",&NullOnFun1,NULL,1};
void NullOnFun2();//空on事件2
struct on_s nullOn2 = {"NullOn2",&NullOnFun2,NULL,2};
//功能:yu头文件,域结构需要用到的公共函数的声明等
//作者:miao
//时间:2010-5-30
#define NULL 0
#define NAME_MAX 32
typedef void (*action_fun)();
typedef void (*on_fun)();
//根域生命值(为零,退出域动作链表循环)
int life = 0;
//动作结构
struct action_s
{
char name[NAME_MAX]; //动作名称
action_fun run; //动作调用的函数
struct action_s *last; //上一动作
struct action_s *next; //下一动作
};
//动作链表
struct actionList_s
{
unsigned int count; //动作计数器
struct action_s *seek; //当前动作
}actionList = {0,NULL};
//添加一个动作到动作链表表里
void AddAction(struct action_s *newAction);
//从动作链表里删除一个动作
void DelAction(struct action_s *delAction);
void Run(); //执行当前动作
void NullActionFun();//空动作,限制链表执行速度或将来用于管理动作链表
struct action_s nullAction = {"NullFun",&NullActionFun,NULL,NULL};
//on事件结构
struct on_s
{
char name[NAME_MAX]; //on事件名称
on_fun run; //on调用的函数
struct on_s *next; //下一个on事件,暂时没有特别用处
char state; //保留,暂时没有特别用处
};
#define ON_LIST_MAX 100
//on事件表结构,双向向内增长堆栈
struct on_list_s
{
struct on_s *list[ON_LIST_MAX]; //on事件堆栈(on事件可以重复)
int idx; //指向lish空的地方
int total; //堆栈中on事件的总数
t_bool flag; //增长标记
}on_list;
//添加一个on事件到on队列(在on队列中on事件可重复添加)
void AddOn(struct on_s *newOn);
void NullOnFun1();//空on事件1
struct on_s nullOn1 = {"NullOn1",&NullOnFun1,NULL,1};
void NullOnFun2();//空on事件2
struct on_s nullOn2 = {"NullOn2",&NullOnFun2,NULL,2};
code:yu.c(改)

//文件:yu.c
//功能:域结构,管理一个动作双向链表,循环执行链表上的动作函数
//作者:miao
//时间:2010-5-30
//添加一个动作到动作链表里
void AddAction(struct action_s *newAction)
{
disp_color_str("add:",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
disp_color_str((*newAction).name,MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
if((*newAction).next != NULL)
{
disp_color_str("**add fail!!**",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
return;
}
if(actionList.count == 0)//若链表里没有元素
{
actionList.seek = newAction;
(*newAction).next = newAction;
(*newAction).last = newAction;
}
else//向动链表表添加一个动作到seek动作指针前
{
(*newAction).last = (*actionList.seek).last;
(*newAction).next = actionList.seek;
(*(*actionList.seek).last).next = newAction;
(*actionList.seek).last = newAction;
}
actionList.count++;
}
//从动作链表里删除一个动作
void DelAction(struct action_s *delAction)
{
disp_color_str(" del:",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
disp_color_str((*delAction).name,MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
//disp_int(actionList.count);
if((*delAction).next == NULL)
{
disp_color_str("**del fail!!**",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
return;
}
if(actionList.count == 0) return;//若链表里没有元素
if(actionList.count == 1)
actionList.seek = NULL;
else //将此动作从链表里移除
{
(*(*delAction).last).next =(*delAction).next;
(*(*delAction).next).last =(*delAction).last;
actionList.seek = (*delAction).last;
}
(*delAction).next = NULL;
(*delAction).last = NULL;
actionList.count--;
}
//添加一个on函数到on队列
void AddOn(struct on_s *newOn)
{
//disp_str("AddOn\n");
if(on_list.total == ON_LIST_MAX)
{
disp_color_str("**on list full!!**",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
return;
}
on_list.list[on_list.idx] = newOn;
on_list.idx += on_list.flag;
on_list.total++;
}
int on_idx;
void Run()
{
//执行当前动作
if(actionList.seek != NULL)
{
(*actionList.seek).run();
}
//处理on事件的控制结构
on_idx = on_list.idx;
asm{cli}
on_list.flag = -on_list.flag;//改变堆栈增长方向
on_list.total=(on_list.idx+ON_LIST_MAX)%ON_LIST_MAX;
on_list.idx=(on_list.flag == 1) ? 0 : ON_LIST_MAX -1;
asm{sti}
//一次性的执行on堆栈中的on事件
for(int i = ((on_list.flag == 1)?ON_LIST_MAX -1:0); i != on_idx; i-=on_list.flag)
{
(*on_list.list[i]).run();
}
//指向下一个动作
if(actionList.seek != NULL)
actionList.seek = (*actionList.seek).next;
}
void sleep(int i);
//使用下面两个on函数打印一个等边三角形
//空on函数1
int testCount = 11;//testCount-2 == 等边三角形边长
void NullOnFun1()
{
if(!testCount) //停止存活
return;
disp_str("* ");
AddOn(&nullOn1);//存活
}
//空on函数2
void NullOnFun2()
{
if(testCount <= 0) //停止存活
return;
disp_next();
for(int i=0;i<testCount;i++)
disp_str(" ");
AddOn(&nullOn2);//存活
AddOn(&nullOn1);//繁殖
testCount--;
}
//空动作,限制链表执行速度或将来用于管理动作链表
void NullActionFun()
{
disp_color_str(" ",MAKE_COLOR(WHITE,RED)| BRIGHT | FLASH);
disp_pos-=2;
sleep(100);
disp_color_str(" ",MAKE_COLOR(BLUE,RED));
disp_pos-=2;
sleep(50);
}
void sleep(int i)
{
while(i--)
for(int i=0;i<100;i++)
for(int j=0;j<100;j++);
}
//功能:域结构,管理一个动作双向链表,循环执行链表上的动作函数
//作者:miao
//时间:2010-5-30
//添加一个动作到动作链表里
void AddAction(struct action_s *newAction)
{
disp_color_str("add:",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
disp_color_str((*newAction).name,MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
if((*newAction).next != NULL)
{
disp_color_str("**add fail!!**",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
return;
}
if(actionList.count == 0)//若链表里没有元素
{
actionList.seek = newAction;
(*newAction).next = newAction;
(*newAction).last = newAction;
}
else//向动链表表添加一个动作到seek动作指针前
{
(*newAction).last = (*actionList.seek).last;
(*newAction).next = actionList.seek;
(*(*actionList.seek).last).next = newAction;
(*actionList.seek).last = newAction;
}
actionList.count++;
}
//从动作链表里删除一个动作
void DelAction(struct action_s *delAction)
{
disp_color_str(" del:",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
disp_color_str((*delAction).name,MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
//disp_int(actionList.count);
if((*delAction).next == NULL)
{
disp_color_str("**del fail!!**",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
return;
}
if(actionList.count == 0) return;//若链表里没有元素
if(actionList.count == 1)
actionList.seek = NULL;
else //将此动作从链表里移除
{
(*(*delAction).last).next =(*delAction).next;
(*(*delAction).next).last =(*delAction).last;
actionList.seek = (*delAction).last;
}
(*delAction).next = NULL;
(*delAction).last = NULL;
actionList.count--;
}
//添加一个on函数到on队列
void AddOn(struct on_s *newOn)
{
//disp_str("AddOn\n");
if(on_list.total == ON_LIST_MAX)
{
disp_color_str("**on list full!!**",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
return;
}
on_list.list[on_list.idx] = newOn;
on_list.idx += on_list.flag;
on_list.total++;
}
int on_idx;
void Run()
{
//执行当前动作
if(actionList.seek != NULL)
{
(*actionList.seek).run();
}
//处理on事件的控制结构
on_idx = on_list.idx;
asm{cli}
on_list.flag = -on_list.flag;//改变堆栈增长方向
on_list.total=(on_list.idx+ON_LIST_MAX)%ON_LIST_MAX;
on_list.idx=(on_list.flag == 1) ? 0 : ON_LIST_MAX -1;
asm{sti}
//一次性的执行on堆栈中的on事件
for(int i = ((on_list.flag == 1)?ON_LIST_MAX -1:0); i != on_idx; i-=on_list.flag)
{
(*on_list.list[i]).run();
}
//指向下一个动作
if(actionList.seek != NULL)
actionList.seek = (*actionList.seek).next;
}
void sleep(int i);
//使用下面两个on函数打印一个等边三角形
//空on函数1
int testCount = 11;//testCount-2 == 等边三角形边长
void NullOnFun1()
{
if(!testCount) //停止存活
return;
disp_str("* ");
AddOn(&nullOn1);//存活
}
//空on函数2
void NullOnFun2()
{
if(testCount <= 0) //停止存活
return;
disp_next();
for(int i=0;i<testCount;i++)
disp_str(" ");
AddOn(&nullOn2);//存活
AddOn(&nullOn1);//繁殖
testCount--;
}
//空动作,限制链表执行速度或将来用于管理动作链表
void NullActionFun()
{
disp_color_str(" ",MAKE_COLOR(WHITE,RED)| BRIGHT | FLASH);
disp_pos-=2;
sleep(100);
disp_color_str(" ",MAKE_COLOR(BLUE,RED));
disp_pos-=2;
sleep(50);
}
void sleep(int i)
{
while(i--)
for(int i=0;i<100;i++)
for(int j=0;j<100;j++);
}
code:keyboard.h(改)

//文件:keyboard.h
//功能:keyboard头文件,内核需要用到的公共函数的声明等
//作者:miao
//时间:2010-5-30
//AT(大口)键盘 8042端口
//键盘数据端口 读:读取输出缓冲器 写:写入输入缓冲器(8042 Data&8048 Command)
#define KB_DATA 0x60
//键盘命令端口 读:读取状态寄存器 写:写入输入缓冲器(8042 Command)
#define KB_CMD 0x64
#define LED_CODE 0xED
#define KB_ACK 0xFA
#define NR_SCAN_CODES 0x54 //扫描码的数目(keymap的行数)除去最后面的不可显示字符的部分
t_32 keymap[NR_SCAN_CODES * 2] = {
//shift未按下 shift按下 扫描码
//!Shift Shift scan code
0, 0, //0x00 - none
0, 0, //0x01 - ESC
'1', '!', //0x02 - '1'
'2', '@', //0x03 - '2'
'3', '#', //0x04 - '3'
'4', '$', //0x05 - '4'
'5', '%', //0x06 - '5'
'6', '^', //0x07 - '6'
'7', '&', //0x08 - '7'
'8', '*', //0x09 - '8'
'9', '(', //0x0A - '9'
'0', ')', //0x0B - '0'
'-', '_', //0x0C - '-'
'=', '+', //0x0D - '='
0, 0, //0x0E - BS
0, 0, //0x0F - TAB
'q', 'Q', //0x10 - 'q'
'w', 'W', //0x11 - 'w'
'e', 'E', //0x12 - 'e'
'r', 'R', //0x13 - 'r'
't', 'T', //0x14 - 't'
'y', 'Y', //0x15 - 'y'
'u', 'U', //0x16 - 'u'
'i', 'I', //0x17 - 'i'
'o', 'O', //0x18 - 'o'
'p', 'P', //0x19 - 'p'
'[', '{', //0x1A - '['
']', '}', //0x1B - ']'
0, 0, //0x1C - CR/LF
0, 0, //0x1D - l. Ctrl
'a', 'A', //0x1E - 'a'
's', 'S', //0x1F - 's'
'd', 'D', //0x20 - 'd'
'f', 'F', //0x21 - 'f'
'g', 'G', //0x22 - 'g'
'h', 'H', //0x23 - 'h'
'j', 'J', //0x24 - 'j'
'k', 'K', //0x25 - 'k'
'l', 'L', //0x26 - 'l'
';', ':', //0x27 - ';'
'\'', '"', //0x28 - '\''
'`', '~', //0x29 - '`'
0, 0, //0x2A - l. SHIFT
'\\', '|', //0x2B - '\'
'z', 'Z', //0x2C - 'z'
'x', 'X', //0x2D - 'x'
'c', 'C', //0x2E - 'c'
'v', 'V', //0x2F - 'v'
'b', 'B', //0x30 - 'b'
'n', 'N', //0x31 - 'n'
'm', 'M', //0x32 - 'm'
',', '<', //0x33 - ','
'.', '>', //0x34 - '.'
'/', '?', //0x35 - '/'
0, 0, //0x36 - r. SHIFT
'*', '*', //0x37 - '*'
0, 0, //0x38 - ALT
' ', ' ', //0x39 - ' '
0, 0, //0x3A - CapsLock
0, 0, //0x3B - F1
0, 0, //0x3C - F2
0, 0, //0x3D - F3
0, 0, //0x3E - F4
0, 0, //0x3F - F5
0, 0, //0x40 - F6
0, 0, //0x41 - F7
0, 0, //0x42 - F8
0, 0, //0x43 - F9
0, 0, //0x44 - F10
0, 0, //0x45 - NumLock
0, 0, //0x46 - ScrLock
0, '7', //0x47 - Home
0, '8', //0x48 - CurUp
0, '9', //0x49 - PgUp
0, '-', //0x4A - '-'
0, '4', //0x4B - Left
0, '5', //0x4C - MID
0, '6', //0x4D - Right
0, '+', //0x4E - '+'
0, '1', //0x4F - End
0, '2', //0x50 - Down
0, '3', //0x51 - PgDown
0, '0', //0x52 - Insert
0, '.', //0x53 - Delete
};
#define KEY_BUF_MAX 32 //键盘输入缓冲区大小
struct keyBuf_s
{
int idx; //缓冲区中共有多少字节
char buf[KEY_BUF_MAX]; //缓冲区
};
void OnKeyEvent(); //键盘中断处理函数
//键盘服务系统相关
int kb_life = 0;
struct keyBuf_s keyBuf[2]; //为了减少对键盘中断的影响,采用双缓冲方式
struct keyBuf_s *busyKeyBuf=&keyBuf[0];//指向键盘中断正在使用的缓冲区
struct keyBuf_s *freeKeyBuf=&keyBuf[1];//指向空闲(待处理)的缓冲区
struct keyBuf_s *keyBufPoint = busyKeyBuf;//键盘中断使用这个缓冲区
t_bool shift; // shift 状态
t_bool capsLock; // Caps Lock 状态
t_bool numLock; // Num Lock 状态
t_bool on0xE0Flag; // 收到0xE0扫描码
t_bool on0xE1Flag; // 收到0xE1扫描码
void init_keyboard();//初始化键盘
void ScanCodeToCharFun();//键码转字符动作函数
struct action_s scanCodeToChar = {"scanCodeToChar",&ScanCodeToCharFun,NULL,NULL};
//和字符处理结合的键盘事件
void OnShiftDownFun();
struct on_s onShiftDown = {"onShiftDown",&OnShiftDownFun,NULL,NULL};
void OnShiftUpFun();
struct on_s onShiftUp = {"onShiftUp",&OnShiftUpFun,NULL,NULL};
void OnCapsLockFun();
struct on_s onCapsLock = {"OnLineDown",&OnCapsLockFun,NULL,NULL};
void OnNumLockFun();
struct on_s onNumLock = {"OnPageUp",&OnNumLockFun,NULL,NULL};
//若碰到E0和E1组合的功能键必须处理,否则可显示字符处理程序会被锁住
void On0xE0Fun();
struct on_s on0xE0 = {"On0xE0",&On0xE0Fun,NULL,NULL};
void On0xE1Fun();
struct on_s on0xE1 = {"On0xE1",&On0xE1Fun,NULL,NULL};
//为所有扫描码或中断码建立一个on事件指针表,根据需要动态管理此表来实现键盘控制功能
struct on_s *keyOntable[0x100] = {
//前 0x80个都是扫描码(键盘按下)
NULL, //0x00 - none
NULL, //0x01 - ESC
NULL, //0x02 - '1'
NULL, //0x03 - '2'
NULL, //0x04 - '3'
NULL, //0x05 - '4'
NULL, //0x06 - '5'
NULL, //0x07 - '6'
NULL, //0x08 - '7'
NULL, //0x09 - '8'
NULL, //0x0A - '9'
NULL, //0x0B - '0'
NULL, //0x0C - '-'
NULL, //0x0D - '='
NULL, //0x0E - BS
NULL, //0x0F - TAB
NULL, //0x10 - 'q'
NULL, //0x11 - 'w'
NULL, //0x12 - 'e'
NULL, //0x13 - 'r'
NULL, //0x14 - 't'
NULL, //0x15 - 'y'
NULL, //0x16 - 'u'
NULL, //0x17 - 'i'
NULL, //0x18 - 'o'
NULL, //0x19 - 'p'
NULL, //0x1A - '['
NULL, //0x1B - ']'
NULL, //0x1C - CR/LF
NULL, //0x1D - l. Ctrl
NULL, //0x1E - 'a'
NULL, //0x1F - 's'
NULL, //0x20 - 'd'
NULL, //0x21 - 'f'
NULL, //0x22 - 'g'
NULL, //0x23 - 'h'
NULL, //0x24 - 'j'
NULL, //0x25 - 'k'
NULL, //0x26 - 'l'
NULL, //0x27 - ';'
NULL, //0x28 - '\''
NULL, //0x29 - '`'
&onShiftDown, //0x2A - l. SHIFT
NULL, //0x2B - '\'
NULL, //0x2C - 'z'
NULL, //0x2D - 'x'
NULL, //0x2E - 'c'
NULL, //0x2F - 'v'
NULL, //0x30 - 'b'
NULL, //0x31 - 'n'
NULL, //0x32 - 'm'
NULL, //0x33 - ','
NULL, //0x34 - '.'
NULL, //0x35 - '/'
&onShiftDown, //0x36 - r. SHIFT
NULL, //0x37 - '*'
NULL, //0x38 - ALT
NULL, //0x39 - ' '
&onCapsLock, //0x3A - CapsLock
NULL, //0x3B - F1
NULL, //0x3C - F2
NULL, //0x3D - F3
NULL, //0x3E - F4
NULL, //0x3F - F5
NULL, //0x40 - F6
NULL, //0x41 - F7
NULL, //0x42 - F8
NULL, //0x43 - F9
NULL, //0x44 - F10
&onNumLock, //0x45 - NumLock
NULL, //0x46 - ScrLock
NULL, //0x47 - Home
&onLineUp, //0x48 - CurUp
&onPageUp, //0x49 - PgUp
NULL, //0x4A - '-'
NULL, //0x4B - Left
NULL, //0x4C - MID
NULL, //0x4D - Right
NULL, //0x4E - '+'
NULL, //0x4F - End
&onLineDown, //0x50 - Down
&onPageDown, //0x51 - PgDown
NULL, //0x52 - Insert
NULL, //0x53 - Delete
NULL, //0x54 - Enter
NULL, //0x55 - ???
NULL, //0x56 - ???
NULL, //0x57 - F11
NULL, //0x58 - F12
NULL, //0x59 - ???
NULL, //0x5A - ???
NULL, //0x5B - ???
NULL, //0x5C - ???
NULL, //0x5D - ???
NULL, //0x5E - ???
NULL, //0x5F - ???
NULL, //0x60 - ???
NULL, //0x61 - ???
NULL, //0x62 - ???
NULL, //0x63 - ???
NULL, //0x64 - ???
NULL, //0x65 - ???
NULL, //0x66 - ???
NULL, //0x67 - ???
NULL, //0x68 - ???
NULL, //0x69 - ???
NULL, //0x6A - ???
NULL, //0x6B - ???
NULL, //0x6C - ???
NULL, //0x6D - ???
NULL, //0x6E - ???
NULL, //0x6F - ???
NULL, //0x70 - ???
NULL, //0x71 - ???
NULL, //0x72 - ???
NULL, //0x73 - ???
NULL, //0x74 - ???
NULL, //0x75 - ???
NULL, //0x76 - ???
NULL, //0x77 - ???
NULL, //0x78 - ???
NULL, //0x79 - ???
NULL, //0x7A - ???
NULL, //0x7B - ???
NULL, //0x7C - ???
NULL, //0x7D - ???
NULL, //0x7E - ???
NULL, //0x7F - ???
//后面 0x80个都是中断码(键盘按键放开)
NULL, //0x80 - none
NULL, //0x81 - ESC
NULL, //0x82 - '1'
NULL, //0x83 - '2'
NULL, //0x84 - '3'
NULL, //0x85 - '4'
NULL, //0x86 - '5'
NULL, //0x87 - '6'
NULL, //0x88 - '7'
NULL, //0x89 - '8'
NULL, //0x8A - '9'
NULL, //0x8B - '0'
NULL, //0x8C - '-'
NULL, //0x8D - '='
NULL, //0x8E - BS
NULL, //0x8F - TAB
NULL, //0x90 - 'q'
NULL, //0x91 - 'w'
NULL, //0x92 - 'e'
NULL, //0x93 - 'r'
NULL, //0x94 - 't'
NULL, //0x95 - 'y'
NULL, //0x96 - 'u'
NULL, //0x97 - 'i'
NULL, //0x98 - 'o'
NULL, //0x99 - 'p'
NULL, //0x9A - '['
NULL, //0x9B - ']'
NULL, //0x9C - CR/LF
NULL, //0x9D - l. Ctrl
NULL, //0x9E - 'a'
NULL, //0x9F - 's'
NULL, //0xA0 - 'd'
NULL, //0xA1 - 'f'
NULL, //0xA2 - 'g'
NULL, //0xA3 - 'r'
NULL, //0xA4 - 'j'
NULL, //0xA5 - 'k'
NULL, //0xA6 - 'l'
NULL, //0xA7 - ';'
NULL, //0xA8 - '\''
NULL, //0xA9 - '`'
&onShiftUp, //0xAA - l. SHIFT
NULL, //0xAB - '\'
NULL, //0xAC - 'z'
NULL, //0xAD - 'x'
NULL, //0xAE - 'c'
NULL, //0xAF - 'v'
NULL, //0xB0 - 'b'
NULL, //0xB1 - 'n'
NULL, //0xB2 - 'm'
NULL, //0xB3 - ','
NULL, //0xB4 - '.'
NULL, //0xB5 - '/'
&onShiftUp, //0xB6 - r. SHIFT
NULL, //0xB7 - '*'
NULL, //0xB8 - ALT
NULL, //0xB9 - ' '
NULL, //0xBA - CapsLock
NULL, //0xBB - F1
NULL, //0xBC - F2
NULL, //0xBD - F3
NULL, //0xBE - F4
NULL, //0xBF - F5
NULL, //0xC0 - F6
NULL, //0xC1 - F7
NULL, //0xC2 - F8
NULL, //0xC3 - F9
NULL, //0xC4 - F10
NULL, //0xC5 - NumLock
NULL, //0xC6 - ScrLock
NULL, //0xC7 - Home
NULL, //0xC8 - CurUp
NULL, //0xC9 - PgUp
NULL, //0xCA - '-'
NULL, //0xCB - Left
NULL, //0xCC - MID
NULL, //0xCD - Right
NULL, //0xCE - '+'
NULL, //0xCF - End
&on0xE0, //0xE0 - Down
&on0xE1, //0xE1 - PgDown
NULL, //0xE2 - Insert
NULL, //0xE3 - Delete
NULL, //0xE4 - Enter
NULL, //0xE5 - ???
NULL, //0xE6 - ???
NULL, //0xE7 - F11
NULL, //0xE8 - F12
NULL, //0xE9 - ???
NULL, //0xEA - ???
NULL, //0xEB - ???
NULL, //0xEC - ???
NULL, //0xED - ???
NULL, //0xEE - ???
NULL, //0xEF - ???
NULL, //0xF0 - ???
NULL, //0xF1 - ???
NULL, //0xF2 - ???
NULL, //0xF3 - ???
NULL, //0xF4 - ???
NULL, //0xF5 - ???
NULL, //0xF6 - ???
NULL, //0xF7 - ???
NULL, //0xF8 - ???
NULL, //0xF9 - ???
NULL, //0xFA - ???
NULL, //0xFB - ???
NULL, //0xFC - ???
NULL, //0xFD - ???
NULL, //0xFE - ???
NULL, //0xFF - ???
NULL, //0xF0 - ???
NULL, //0xF1 - ???
NULL, //0xF2 - ???
NULL, //0xF3 - ???
NULL, //0xF4 - ???
NULL, //0xF5 - ???
NULL, //0xF6 - ???
NULL, //0xF7 - ???
NULL, //0xF8 - ???
NULL, //0xF9 - ???
NULL, //0xFA - ???
NULL, //0xFB - ???
NULL, //0xFC - ???
NULL, //0xFD - ???
NULL, //0xFE - ???
NULL, //0xFF - ???
};
//功能:keyboard头文件,内核需要用到的公共函数的声明等
//作者:miao
//时间:2010-5-30
//AT(大口)键盘 8042端口
//键盘数据端口 读:读取输出缓冲器 写:写入输入缓冲器(8042 Data&8048 Command)
#define KB_DATA 0x60
//键盘命令端口 读:读取状态寄存器 写:写入输入缓冲器(8042 Command)
#define KB_CMD 0x64
#define LED_CODE 0xED
#define KB_ACK 0xFA
#define NR_SCAN_CODES 0x54 //扫描码的数目(keymap的行数)除去最后面的不可显示字符的部分
t_32 keymap[NR_SCAN_CODES * 2] = {
//shift未按下 shift按下 扫描码
//!Shift Shift scan code
0, 0, //0x00 - none
0, 0, //0x01 - ESC
'1', '!', //0x02 - '1'
'2', '@', //0x03 - '2'
'3', '#', //0x04 - '3'
'4', '$', //0x05 - '4'
'5', '%', //0x06 - '5'
'6', '^', //0x07 - '6'
'7', '&', //0x08 - '7'
'8', '*', //0x09 - '8'
'9', '(', //0x0A - '9'
'0', ')', //0x0B - '0'
'-', '_', //0x0C - '-'
'=', '+', //0x0D - '='
0, 0, //0x0E - BS
0, 0, //0x0F - TAB
'q', 'Q', //0x10 - 'q'
'w', 'W', //0x11 - 'w'
'e', 'E', //0x12 - 'e'
'r', 'R', //0x13 - 'r'
't', 'T', //0x14 - 't'
'y', 'Y', //0x15 - 'y'
'u', 'U', //0x16 - 'u'
'i', 'I', //0x17 - 'i'
'o', 'O', //0x18 - 'o'
'p', 'P', //0x19 - 'p'
'[', '{', //0x1A - '['
']', '}', //0x1B - ']'
0, 0, //0x1C - CR/LF
0, 0, //0x1D - l. Ctrl
'a', 'A', //0x1E - 'a'
's', 'S', //0x1F - 's'
'd', 'D', //0x20 - 'd'
'f', 'F', //0x21 - 'f'
'g', 'G', //0x22 - 'g'
'h', 'H', //0x23 - 'h'
'j', 'J', //0x24 - 'j'
'k', 'K', //0x25 - 'k'
'l', 'L', //0x26 - 'l'
';', ':', //0x27 - ';'
'\'', '"', //0x28 - '\''
'`', '~', //0x29 - '`'
0, 0, //0x2A - l. SHIFT
'\\', '|', //0x2B - '\'
'z', 'Z', //0x2C - 'z'
'x', 'X', //0x2D - 'x'
'c', 'C', //0x2E - 'c'
'v', 'V', //0x2F - 'v'
'b', 'B', //0x30 - 'b'
'n', 'N', //0x31 - 'n'
'm', 'M', //0x32 - 'm'
',', '<', //0x33 - ','
'.', '>', //0x34 - '.'
'/', '?', //0x35 - '/'
0, 0, //0x36 - r. SHIFT
'*', '*', //0x37 - '*'
0, 0, //0x38 - ALT
' ', ' ', //0x39 - ' '
0, 0, //0x3A - CapsLock
0, 0, //0x3B - F1
0, 0, //0x3C - F2
0, 0, //0x3D - F3
0, 0, //0x3E - F4
0, 0, //0x3F - F5
0, 0, //0x40 - F6
0, 0, //0x41 - F7
0, 0, //0x42 - F8
0, 0, //0x43 - F9
0, 0, //0x44 - F10
0, 0, //0x45 - NumLock
0, 0, //0x46 - ScrLock
0, '7', //0x47 - Home
0, '8', //0x48 - CurUp
0, '9', //0x49 - PgUp
0, '-', //0x4A - '-'
0, '4', //0x4B - Left
0, '5', //0x4C - MID
0, '6', //0x4D - Right
0, '+', //0x4E - '+'
0, '1', //0x4F - End
0, '2', //0x50 - Down
0, '3', //0x51 - PgDown
0, '0', //0x52 - Insert
0, '.', //0x53 - Delete
};
#define KEY_BUF_MAX 32 //键盘输入缓冲区大小
struct keyBuf_s
{
int idx; //缓冲区中共有多少字节
char buf[KEY_BUF_MAX]; //缓冲区
};
void OnKeyEvent(); //键盘中断处理函数
//键盘服务系统相关
int kb_life = 0;
struct keyBuf_s keyBuf[2]; //为了减少对键盘中断的影响,采用双缓冲方式
struct keyBuf_s *busyKeyBuf=&keyBuf[0];//指向键盘中断正在使用的缓冲区
struct keyBuf_s *freeKeyBuf=&keyBuf[1];//指向空闲(待处理)的缓冲区
struct keyBuf_s *keyBufPoint = busyKeyBuf;//键盘中断使用这个缓冲区
t_bool shift; // shift 状态
t_bool capsLock; // Caps Lock 状态
t_bool numLock; // Num Lock 状态
t_bool on0xE0Flag; // 收到0xE0扫描码
t_bool on0xE1Flag; // 收到0xE1扫描码
void init_keyboard();//初始化键盘
void ScanCodeToCharFun();//键码转字符动作函数
struct action_s scanCodeToChar = {"scanCodeToChar",&ScanCodeToCharFun,NULL,NULL};
//和字符处理结合的键盘事件
void OnShiftDownFun();
struct on_s onShiftDown = {"onShiftDown",&OnShiftDownFun,NULL,NULL};
void OnShiftUpFun();
struct on_s onShiftUp = {"onShiftUp",&OnShiftUpFun,NULL,NULL};
void OnCapsLockFun();
struct on_s onCapsLock = {"OnLineDown",&OnCapsLockFun,NULL,NULL};
void OnNumLockFun();
struct on_s onNumLock = {"OnPageUp",&OnNumLockFun,NULL,NULL};
//若碰到E0和E1组合的功能键必须处理,否则可显示字符处理程序会被锁住
void On0xE0Fun();
struct on_s on0xE0 = {"On0xE0",&On0xE0Fun,NULL,NULL};
void On0xE1Fun();
struct on_s on0xE1 = {"On0xE1",&On0xE1Fun,NULL,NULL};
//为所有扫描码或中断码建立一个on事件指针表,根据需要动态管理此表来实现键盘控制功能
struct on_s *keyOntable[0x100] = {
//前 0x80个都是扫描码(键盘按下)
NULL, //0x00 - none
NULL, //0x01 - ESC
NULL, //0x02 - '1'
NULL, //0x03 - '2'
NULL, //0x04 - '3'
NULL, //0x05 - '4'
NULL, //0x06 - '5'
NULL, //0x07 - '6'
NULL, //0x08 - '7'
NULL, //0x09 - '8'
NULL, //0x0A - '9'
NULL, //0x0B - '0'
NULL, //0x0C - '-'
NULL, //0x0D - '='
NULL, //0x0E - BS
NULL, //0x0F - TAB
NULL, //0x10 - 'q'
NULL, //0x11 - 'w'
NULL, //0x12 - 'e'
NULL, //0x13 - 'r'
NULL, //0x14 - 't'
NULL, //0x15 - 'y'
NULL, //0x16 - 'u'
NULL, //0x17 - 'i'
NULL, //0x18 - 'o'
NULL, //0x19 - 'p'
NULL, //0x1A - '['
NULL, //0x1B - ']'
NULL, //0x1C - CR/LF
NULL, //0x1D - l. Ctrl
NULL, //0x1E - 'a'
NULL, //0x1F - 's'
NULL, //0x20 - 'd'
NULL, //0x21 - 'f'
NULL, //0x22 - 'g'
NULL, //0x23 - 'h'
NULL, //0x24 - 'j'
NULL, //0x25 - 'k'
NULL, //0x26 - 'l'
NULL, //0x27 - ';'
NULL, //0x28 - '\''
NULL, //0x29 - '`'
&onShiftDown, //0x2A - l. SHIFT
NULL, //0x2B - '\'
NULL, //0x2C - 'z'
NULL, //0x2D - 'x'
NULL, //0x2E - 'c'
NULL, //0x2F - 'v'
NULL, //0x30 - 'b'
NULL, //0x31 - 'n'
NULL, //0x32 - 'm'
NULL, //0x33 - ','
NULL, //0x34 - '.'
NULL, //0x35 - '/'
&onShiftDown, //0x36 - r. SHIFT
NULL, //0x37 - '*'
NULL, //0x38 - ALT
NULL, //0x39 - ' '
&onCapsLock, //0x3A - CapsLock
NULL, //0x3B - F1
NULL, //0x3C - F2
NULL, //0x3D - F3
NULL, //0x3E - F4
NULL, //0x3F - F5
NULL, //0x40 - F6
NULL, //0x41 - F7
NULL, //0x42 - F8
NULL, //0x43 - F9
NULL, //0x44 - F10
&onNumLock, //0x45 - NumLock
NULL, //0x46 - ScrLock
NULL, //0x47 - Home
&onLineUp, //0x48 - CurUp
&onPageUp, //0x49 - PgUp
NULL, //0x4A - '-'
NULL, //0x4B - Left
NULL, //0x4C - MID
NULL, //0x4D - Right
NULL, //0x4E - '+'
NULL, //0x4F - End
&onLineDown, //0x50 - Down
&onPageDown, //0x51 - PgDown
NULL, //0x52 - Insert
NULL, //0x53 - Delete
NULL, //0x54 - Enter
NULL, //0x55 - ???
NULL, //0x56 - ???
NULL, //0x57 - F11
NULL, //0x58 - F12
NULL, //0x59 - ???
NULL, //0x5A - ???
NULL, //0x5B - ???
NULL, //0x5C - ???
NULL, //0x5D - ???
NULL, //0x5E - ???
NULL, //0x5F - ???
NULL, //0x60 - ???
NULL, //0x61 - ???
NULL, //0x62 - ???
NULL, //0x63 - ???
NULL, //0x64 - ???
NULL, //0x65 - ???
NULL, //0x66 - ???
NULL, //0x67 - ???
NULL, //0x68 - ???
NULL, //0x69 - ???
NULL, //0x6A - ???
NULL, //0x6B - ???
NULL, //0x6C - ???
NULL, //0x6D - ???
NULL, //0x6E - ???
NULL, //0x6F - ???
NULL, //0x70 - ???
NULL, //0x71 - ???
NULL, //0x72 - ???
NULL, //0x73 - ???
NULL, //0x74 - ???
NULL, //0x75 - ???
NULL, //0x76 - ???
NULL, //0x77 - ???
NULL, //0x78 - ???
NULL, //0x79 - ???
NULL, //0x7A - ???
NULL, //0x7B - ???
NULL, //0x7C - ???
NULL, //0x7D - ???
NULL, //0x7E - ???
NULL, //0x7F - ???
//后面 0x80个都是中断码(键盘按键放开)
NULL, //0x80 - none
NULL, //0x81 - ESC
NULL, //0x82 - '1'
NULL, //0x83 - '2'
NULL, //0x84 - '3'
NULL, //0x85 - '4'
NULL, //0x86 - '5'
NULL, //0x87 - '6'
NULL, //0x88 - '7'
NULL, //0x89 - '8'
NULL, //0x8A - '9'
NULL, //0x8B - '0'
NULL, //0x8C - '-'
NULL, //0x8D - '='
NULL, //0x8E - BS
NULL, //0x8F - TAB
NULL, //0x90 - 'q'
NULL, //0x91 - 'w'
NULL, //0x92 - 'e'
NULL, //0x93 - 'r'
NULL, //0x94 - 't'
NULL, //0x95 - 'y'
NULL, //0x96 - 'u'
NULL, //0x97 - 'i'
NULL, //0x98 - 'o'
NULL, //0x99 - 'p'
NULL, //0x9A - '['
NULL, //0x9B - ']'
NULL, //0x9C - CR/LF
NULL, //0x9D - l. Ctrl
NULL, //0x9E - 'a'
NULL, //0x9F - 's'
NULL, //0xA0 - 'd'
NULL, //0xA1 - 'f'
NULL, //0xA2 - 'g'
NULL, //0xA3 - 'r'
NULL, //0xA4 - 'j'
NULL, //0xA5 - 'k'
NULL, //0xA6 - 'l'
NULL, //0xA7 - ';'
NULL, //0xA8 - '\''
NULL, //0xA9 - '`'
&onShiftUp, //0xAA - l. SHIFT
NULL, //0xAB - '\'
NULL, //0xAC - 'z'
NULL, //0xAD - 'x'
NULL, //0xAE - 'c'
NULL, //0xAF - 'v'
NULL, //0xB0 - 'b'
NULL, //0xB1 - 'n'
NULL, //0xB2 - 'm'
NULL, //0xB3 - ','
NULL, //0xB4 - '.'
NULL, //0xB5 - '/'
&onShiftUp, //0xB6 - r. SHIFT
NULL, //0xB7 - '*'
NULL, //0xB8 - ALT
NULL, //0xB9 - ' '
NULL, //0xBA - CapsLock
NULL, //0xBB - F1
NULL, //0xBC - F2
NULL, //0xBD - F3
NULL, //0xBE - F4
NULL, //0xBF - F5
NULL, //0xC0 - F6
NULL, //0xC1 - F7
NULL, //0xC2 - F8
NULL, //0xC3 - F9
NULL, //0xC4 - F10
NULL, //0xC5 - NumLock
NULL, //0xC6 - ScrLock
NULL, //0xC7 - Home
NULL, //0xC8 - CurUp
NULL, //0xC9 - PgUp
NULL, //0xCA - '-'
NULL, //0xCB - Left
NULL, //0xCC - MID
NULL, //0xCD - Right
NULL, //0xCE - '+'
NULL, //0xCF - End
&on0xE0, //0xE0 - Down
&on0xE1, //0xE1 - PgDown
NULL, //0xE2 - Insert
NULL, //0xE3 - Delete
NULL, //0xE4 - Enter
NULL, //0xE5 - ???
NULL, //0xE6 - ???
NULL, //0xE7 - F11
NULL, //0xE8 - F12
NULL, //0xE9 - ???
NULL, //0xEA - ???
NULL, //0xEB - ???
NULL, //0xEC - ???
NULL, //0xED - ???
NULL, //0xEE - ???
NULL, //0xEF - ???
NULL, //0xF0 - ???
NULL, //0xF1 - ???
NULL, //0xF2 - ???
NULL, //0xF3 - ???
NULL, //0xF4 - ???
NULL, //0xF5 - ???
NULL, //0xF6 - ???
NULL, //0xF7 - ???
NULL, //0xF8 - ???
NULL, //0xF9 - ???
NULL, //0xFA - ???
NULL, //0xFB - ???
NULL, //0xFC - ???
NULL, //0xFD - ???
NULL, //0xFE - ???
NULL, //0xFF - ???
NULL, //0xF0 - ???
NULL, //0xF1 - ???
NULL, //0xF2 - ???
NULL, //0xF3 - ???
NULL, //0xF4 - ???
NULL, //0xF5 - ???
NULL, //0xF6 - ???
NULL, //0xF7 - ???
NULL, //0xF8 - ???
NULL, //0xF9 - ???
NULL, //0xFA - ???
NULL, //0xFB - ???
NULL, //0xFC - ???
NULL, //0xFD - ???
NULL, //0xFE - ???
NULL, //0xFF - ???
};
code:keyboard.c(改)

//文件:keyboard.c
//功能:初始化键盘、以及设置中断相关的函数
//作者:miao
//时间:2010-5-30
//键盘中断处理函数
void OnKeyEvent()
{
t_8 scan_code = in_byte(KB_DATA); //获取扫描码
//disp_int(scan_code);
//disp_str(" ");
//return;
//处理属于控制性质的按键扫描码
struct on_s *keyOnPoin = keyOntable[scan_code];
if(keyOnPoin != NULL)
{
AddOn(keyOnPoin); //加入On事件队列
keyOntable[scan_code]=NULL;
}
//处理属于字符扫描码
//键盘域生命值为负,表示不需要对字符扫描码,同时排除中断码
if(kb_life<0 || scan_code >= 0x80 )//|| on0xE0Flag || on0xE1Flag)
return ; //在实现所有E0,E1的功能键时,需要过滤掉功能键对应的可显示字符
//将扫描法放入缓冲区
if(keyBufPoint->idx < KEY_BUF_MAX) //若缓冲区未满,记录信息
{
keyBufPoint->buf[keyBufPoint->idx++] = scan_code; //记录扫描码
}
else
disp_color_str("**keyBuf full!!**",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
if(kb_life==0)//当键盘生命值为零,表示键盘字符处理动作不在执行链表里
{
kb_life=1;
AddAction(&scanCodeToChar);//加载键盘服务域
}
}
void InitKeyOnEvent(struct on_s *newOn, t_8 scan_code)
{
(*newOn).next = keyOntable[scan_code];
keyOntable[scan_code]=newOn;
}
void OnShiftDownFun()
{
if(shift==1)
return;
shift = 1;
InitKeyOnEvent(onShiftUp,0xAA);
return;
}
void OnShiftUpFun()
{
shift = 0;
InitKeyOnEvent(onShiftDown,0x2A);
return;
}
void OnCapsLockFun()
{
capsLock = !capsLock;
InitKeyOnEvent(onCapsLock,0x3A);
return;
}
void OnNumLockFun()
{
numLock = !numLock;
InitKeyOnEvent(onNumLock,0x45);
return;
}
void On0xE0Fun()
{
disp_str("On0xE0Fun ");
on0xE0Flag = 1;
return;
}
void On0xE1Fun()
{
disp_str("On0xE1Fun ");
on0xE1Flag = 1;
return;
}
//键盘中断初始化函数
void init_keyboard()
{
kb_life = 0;//键盘域的生命值
//初始化键盘缓冲区
keyBuf[0].idx=0;
keyBuf[1].idx=0;
busyKeyBuf=&keyBuf[0];//指向键盘中断正在使用的缓冲区
freeKeyBuf=&keyBuf[1];//指向空闲(待处理)的缓冲区
keyBufPoint = busyKeyBuf;//键盘中断使用这个缓冲区
//初始化键盘标记
capsLock = 0;
numLock = 1;
shift = 0;
enable_irq(KEYBOARD_IRQ); //开键盘中断
}
//将缓冲区里扫描码转换成相应的字符,然后进行后续处理
t_bool make; //TRUE:make FALSE:break
t_32 *keyrow; //指向 keymap[] 的某一行
t_32 key = 0; //用一个整型来表示一个键。
char moutput[2]=" ";
//键盘字符处理动作
void ScanCodeToCharFun()
{
//交换双缓冲区
asm{cli}
keyBufPoint = freeKeyBuf;
freeKeyBuf = busyKeyBuf;
busyKeyBuf = keyBufPoint;
asm{sti}
if(freeKeyBuf->idx == 0) //若没有记录,不处理
{
kb_life++;
if(kb_life>=20)//当空闲次数多时,撤销键盘字符处理动作
{
kb_life = 0;
DelAction(&scanCodeToChar);
}
return;
}
//提取缓冲区中扫描码对应的可显示字符
for(int i = 0;i<freeKeyBuf->idx;i++)
{
make = freeKeyBuf->buf[i];//取得扫描码
//先定位到 keymap 中的行
keyrow = &keymap[make * 2];
if(shift)//根据是否按下shift,取不同的值
key = keyrow[1];
else
key = keyrow[0];
//若 Caps Lock 键被按下 字符大小写要互换
if(capsLock && ((key >='a' && key<='z') || (key >='A'&& key<='Z')))
key^=0x20;
//不是字母,若是小键盘区的扫描码且 Num Lock 按下,要显示小键盘的字符
else if( make >= 0x47 && numLock)
key = keyrow[1];
if (key == 0)//排除非可显示字符
continue;
//此时,key已经是可显示字符的ASCII码了,下面根据需要进行处理
moutput[0]= key;// key & 0xFF;
disp_str(moutput);//简单显示出来
}
freeKeyBuf->idx = 0;
}
//功能:初始化键盘、以及设置中断相关的函数
//作者:miao
//时间:2010-5-30
//键盘中断处理函数
void OnKeyEvent()
{
t_8 scan_code = in_byte(KB_DATA); //获取扫描码
//disp_int(scan_code);
//disp_str(" ");
//return;
//处理属于控制性质的按键扫描码
struct on_s *keyOnPoin = keyOntable[scan_code];
if(keyOnPoin != NULL)
{
AddOn(keyOnPoin); //加入On事件队列
keyOntable[scan_code]=NULL;
}
//处理属于字符扫描码
//键盘域生命值为负,表示不需要对字符扫描码,同时排除中断码
if(kb_life<0 || scan_code >= 0x80 )//|| on0xE0Flag || on0xE1Flag)
return ; //在实现所有E0,E1的功能键时,需要过滤掉功能键对应的可显示字符
//将扫描法放入缓冲区
if(keyBufPoint->idx < KEY_BUF_MAX) //若缓冲区未满,记录信息
{
keyBufPoint->buf[keyBufPoint->idx++] = scan_code; //记录扫描码
}
else
disp_color_str("**keyBuf full!!**",MAKE_COLOR(BLUE,RED)|BRIGHT|FLASH);
if(kb_life==0)//当键盘生命值为零,表示键盘字符处理动作不在执行链表里
{
kb_life=1;
AddAction(&scanCodeToChar);//加载键盘服务域
}
}
void InitKeyOnEvent(struct on_s *newOn, t_8 scan_code)
{
(*newOn).next = keyOntable[scan_code];
keyOntable[scan_code]=newOn;
}
void OnShiftDownFun()
{
if(shift==1)
return;
shift = 1;
InitKeyOnEvent(onShiftUp,0xAA);
return;
}
void OnShiftUpFun()
{
shift = 0;
InitKeyOnEvent(onShiftDown,0x2A);
return;
}
void OnCapsLockFun()
{
capsLock = !capsLock;
InitKeyOnEvent(onCapsLock,0x3A);
return;
}
void OnNumLockFun()
{
numLock = !numLock;
InitKeyOnEvent(onNumLock,0x45);
return;
}
void On0xE0Fun()
{
disp_str("On0xE0Fun ");
on0xE0Flag = 1;
return;
}
void On0xE1Fun()
{
disp_str("On0xE1Fun ");
on0xE1Flag = 1;
return;
}
//键盘中断初始化函数
void init_keyboard()
{
kb_life = 0;//键盘域的生命值
//初始化键盘缓冲区
keyBuf[0].idx=0;
keyBuf[1].idx=0;
busyKeyBuf=&keyBuf[0];//指向键盘中断正在使用的缓冲区
freeKeyBuf=&keyBuf[1];//指向空闲(待处理)的缓冲区
keyBufPoint = busyKeyBuf;//键盘中断使用这个缓冲区
//初始化键盘标记
capsLock = 0;
numLock = 1;
shift = 0;
enable_irq(KEYBOARD_IRQ); //开键盘中断
}
//将缓冲区里扫描码转换成相应的字符,然后进行后续处理
t_bool make; //TRUE:make FALSE:break
t_32 *keyrow; //指向 keymap[] 的某一行
t_32 key = 0; //用一个整型来表示一个键。
char moutput[2]=" ";
//键盘字符处理动作
void ScanCodeToCharFun()
{
//交换双缓冲区
asm{cli}
keyBufPoint = freeKeyBuf;
freeKeyBuf = busyKeyBuf;
busyKeyBuf = keyBufPoint;
asm{sti}
if(freeKeyBuf->idx == 0) //若没有记录,不处理
{
kb_life++;
if(kb_life>=20)//当空闲次数多时,撤销键盘字符处理动作
{
kb_life = 0;
DelAction(&scanCodeToChar);
}
return;
}
//提取缓冲区中扫描码对应的可显示字符
for(int i = 0;i<freeKeyBuf->idx;i++)
{
make = freeKeyBuf->buf[i];//取得扫描码
//先定位到 keymap 中的行
keyrow = &keymap[make * 2];
if(shift)//根据是否按下shift,取不同的值
key = keyrow[1];
else
key = keyrow[0];
//若 Caps Lock 键被按下 字符大小写要互换
if(capsLock && ((key >='a' && key<='z') || (key >='A'&& key<='Z')))
key^=0x20;
//不是字母,若是小键盘区的扫描码且 Num Lock 按下,要显示小键盘的字符
else if( make >= 0x47 && numLock)
key = keyrow[1];
if (key == 0)//排除非可显示字符
continue;
//此时,key已经是可显示字符的ASCII码了,下面根据需要进行处理
moutput[0]= key;// key & 0xFF;
disp_str(moutput);//简单显示出来
}
freeKeyBuf->idx = 0;
}