Appearance
day13定时器
优化字符显示的函数
c
// 要改变的图层, 初始位置, 字符的颜色, 背景的颜色, 字符串, 长度
void putfonts8_asc_sht(struct SHEET *sht, int x, int y, int c, int b, char *s, int l)
{
boxfill8(sht->buf, sht->bxsize, b, x, y, x + l * 8 - 1, y + 15);
putfonts8_asc(sht->buf, sht->bxsize, x, y, c, s);
sheet_refresh(sht, x, y, x + l * 8, y + 16);
return;
}
把三个函数整合到一个函数
所有的中断信号使用同一个FIFO
- 0-1 光标闪烁使用的定时器
- 3 3秒的定时器
- 10 10秒的定时器
- 256-511 键盘输入
- 512-767 鼠标输入
首先实现32位的FIFO
c
void fifo32_init(struct FIFO32 *fifo, int size, int *buf)
/* FIFO初始化 */
{
fifo->size = size;
fifo->buf = buf;
fifo->free = size; /* 空き */
fifo->flags = 0;
fifo->p = 0; /* 書き込み位置 */
fifo->q = 0; /* 読み込み位置 */
return;
}
int fifo32_put(struct FIFO32 *fifo, int data)
/* FIFO放入一个数据 */
{
if (fifo->free == 0) {
/* 没有空位了 */
fifo->flags |= FLAGS_OVERRUN;
return -1;
}
fifo->buf[fifo->p] = data;
fifo->p++;
if (fifo->p == fifo->size) {
fifo->p = 0;
}
fifo->free--;
return 0;
}
int fifo32_get(struct FIFO32 *fifo)
/* FIFO获取其中一个 */
{
int data;
if (fifo->free == fifo->size) {
/* 没有数据 */
return -1;
}
data = fifo->buf[fifo->q];
fifo->q++;
if (fifo->q == fifo->size) {
fifo->q = 0;
}
fifo->free++;
return data;
}
int fifo32_status(struct FIFO32 *fifo)
/* 获取剩余的数量 */
{
return fifo->size - fifo->free;
}
c
struct FIFO32 *keyfifo;
int keydata0;
void inthandler21(int *esp)
{
int data;
io_out8(PIC0_OCW2, 0x61); /* IRQ-01 */
data = io_in8(PORT_KEYDAT);
//偏移
fifo32_put(keyfifo, data + keydata0);
return;
}
void init_keyboard(struct FIFO32 *fifo, int data0)
{
/* 将FIFO的信息保存起来,以及保存偏移 */
keyfifo = fifo;
keydata0 = data0;
/* 进行初始化 */
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
wait_KBC_sendready();
io_out8(PORT_KEYDAT, KBC_MODE);
return;
}
c
struct FIFO32 *mousefifo;
int mousedata0;
void inthandler2c(int *esp)
/* PS/2鼠标的中断 */
{
int data;
io_out8(PIC1_OCW2, 0x64);
io_out8(PIC0_OCW2, 0x62);
data = io_in8(PORT_KEYDAT);
//偏移
fifo32_put(mousefifo, data + mousedata0);
return;
}
#define KEYCMD_SENDTO_MOUSE 0xd4
#define MOUSECMD_ENABLE 0xf4
void enable_mouse(struct FIFO32 *fifo, int data0, struct MOUSE_DEC *mdec)
{
/* 记录偏移量以及fifo */
mousefifo = fifo;
mousedata0 = data0;
/* 初始化 */
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
wait_KBC_sendready();
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
/* 顺利的话会发送0xfa */
mdec->phase = 0; /* 等待鼠标 */
return;
}
c
void HariMain(void)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
struct FIFO32 fifo;
char s[40];
int fifobuf[128];
struct TIMER *timer, *timer2, *timer3;
int mx, my, i, count = 0;
unsigned int memtotal;
struct MOUSE_DEC mdec;
struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
struct SHTCTL *shtctl;
struct SHEET *sht_back, *sht_mouse, *sht_win;
unsigned char *buf_back, buf_mouse[256], *buf_win;
init_gdtidt();
init_pic();
io_sti(); /* IDT/PICの初期化が終わったのでCPUの割り込み禁止を解除 */
fifo32_init(&fifo, 128, fifobuf);
init_pit();
//设置偏移以及fifo
init_keyboard(&fifo, 256);
enable_mouse(&fifo, 512, &mdec);
io_out8(PIC0_IMR, 0xf8); /* PITとPIC1とキーボードを許可(11111000) */
io_out8(PIC1_IMR, 0xef); /* マウスを許可(11101111) */
timer = timer_alloc();
timer_init(timer, &fifo, 10);
timer_settime(timer, 1000);
timer2 = timer_alloc();
timer_init(timer2, &fifo, 3);
timer_settime(timer2, 300);
timer3 = timer_alloc();
timer_init(timer3, &fifo, 1);
timer_settime(timer3, 50);
memtotal = memtest(0x00400000, 0xbfffffff);
memman_init(memman);
memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 0x0009efff */
memman_free(memman, 0x00400000, memtotal - 0x00400000);
init_palette();
shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);
sht_back = sheet_alloc(shtctl);
sht_mouse = sheet_alloc(shtctl);
sht_win = sheet_alloc(shtctl);
buf_back = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);
buf_win = (unsigned char *) memman_alloc_4k(memman, 160 * 52);
sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /* 透明色なし */
sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99);
sheet_setbuf(sht_win, buf_win, 160, 52, -1); /* 透明色なし */
init_screen8(buf_back, binfo->scrnx, binfo->scrny);
init_mouse_cursor8(buf_mouse, 99);
make_window8(buf_win, 160, 52, "counter");
sheet_slide(sht_back, 0, 0);
mx = (binfo->scrnx - 16) / 2; /* 画面中央になるように座標計算 */
my = (binfo->scrny - 28 - 16) / 2;
sheet_slide(sht_mouse, mx, my);
sheet_slide(sht_win, 80, 72);
sheet_updown(sht_back, 0);
sheet_updown(sht_win, 1);
sheet_updown(sht_mouse, 2);
sprintf(s, "(%3d, %3d)", mx, my);
putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
sprintf(s, "memory %dMB free : %dKB",
memtotal / (1024 * 1024), memman_total(memman) / 1024);
putfonts8_asc_sht(sht_back, 0, 32, COL8_FFFFFF, COL8_008484, s, 40);
for (;;) {
count++;
io_cli();
if (fifo32_status(&fifo) == 0) {
io_sti();
} else {
i = fifo32_get(&fifo);
io_sti();
if (256 <= i && i <= 511) { /* キーボードデータ */
sprintf(s, "%02X", i - 256);
putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
} else if (512 <= i && i <= 767) { /* マウスデータ */
if (mouse_decode(&mdec, i - 512) != 0) {
/* 这里面的是鼠标的数据 */
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
if ((mdec.btn & 0x01) != 0) {
s[1] = 'L';
}
if ((mdec.btn & 0x02) != 0) {
s[3] = 'R';
}
if ((mdec.btn & 0x04) != 0) {
s[2] = 'C';
}
putfonts8_asc_sht(sht_back, 32, 16, COL8_FFFFFF, COL8_008484, s, 15);
/* 对鼠标的位置进行变换 */
mx += mdec.x;
my += mdec.y;
if (mx < 0) {
mx = 0;
}
if (my < 0) {
my = 0;
}
if (mx > binfo->scrnx - 1) {
mx = binfo->scrnx - 1;
}
if (my > binfo->scrny - 1) {
my = binfo->scrny - 1;
}
sprintf(s, "(%3d, %3d)", mx, my);
putfonts8_asc_sht(sht_back, 0, 0, COL8_FFFFFF, COL8_008484, s, 10);
sheet_slide(sht_mouse, mx, my);
}
} else if (i == 10) { /* 10秒 */
putfonts8_asc_sht(sht_back, 0, 64, COL8_FFFFFF, COL8_008484, "10[sec]", 7);
sprintf(s, "%010d", count);
putfonts8_asc_sht(sht_win, 40, 28, COL8_000000, COL8_C6C6C6, s, 10);
} else if (i == 3) { /* 3秒 */
putfonts8_asc_sht(sht_back, 0, 80, COL8_FFFFFF, COL8_008484, "3[sec]", 6);
count = 0; /* 开始检测 */
} else if (i == 1) { /* 这个是闪烁 */
timer_init(timer3, &fifo, 0); /* 设置为返回0 */
boxfill8(buf_back, binfo->scrnx, COL8_FFFFFF, 8, 96, 15, 111);
timer_settime(timer3, 50);
sheet_refresh(sht_back, 8, 96, 16, 112);
} else if (i == 0) { /* 设置为返回1 */
timer_init(timer3, &fifo, 1); /* 次は1を */
boxfill8(buf_back, binfo->scrnx, COL8_008484, 8, 96, 15, 111);
timer_settime(timer3, 50);
sheet_refresh(sht_back, 8, 96, 16, 112);
}
}
}
}
引入链表
c
struct TIMER {
struct TIMER *next;
unsigned int timeout, flags;
struct FIFO32 *fifo;
int data;
};
struct TIMERCTL {
unsigned int count, next, using;
struct TIMER *t0;
struct TIMER timers0[MAX_TIMER];
};
c
void inthandler20(int *esp)
{
int i;
struct TIMER *timer;
io_out8(PIC0_OCW2, 0x60); /* IRQ-00 */
timerctl.count++;
if (timerctl.next > timerctl.count) {
return;
}
timer = timerctl.t0; /* 获取链表的头部 */
for (i = 0; i < timerctl.using; i++) {
/* 处理到时间的, 获取下一位需处理的链表 */
if (timer->timeout > timerctl.count) {
break;
}
/* 设置标志位 */
timer->flags = TIMER_FLAGS_ALLOC;
fifo32_put(timer->fifo, timer->data);
timer = timer->next; /* 来到下一个链表 */
}
timerctl.using -= i;
/* 更新 */
timerctl.t0 = timer;
/* timerctl.next的设置, 还有时钟在使用的话就进行设置 */
if (timerctl.using > 0) {
timerctl.next = timerctl.t0->timeout;
} else {
timerctl.next = 0xffffffff;
}
return;
}
c
void timer_settime(struct TIMER *timer, unsigned int timeout)
{
int e;
struct TIMER *t, *s;
//获取实际超时的时间
timer->timeout = timeout + timerctl.count;
timer->flags = TIMER_FLAGS_USING;
//进入临界区
e = io_load_eflags();
io_cli();
timerctl.using++;
if (timerctl.using == 1) {
/* 正在使用的链表只有他自己 */
timerctl.t0 = timer;
timer->next = 0; /* 没有下一个*/
timerctl.next = timer->timeout;
io_store_eflags(e);
return;
}
//获取当前的时钟
t = timerctl.t0;
if (timer->timeout <= t->timeout) {
/* 当前的时钟下一次的时间大于新设置的时间 */
timerctl.t0 = timer;
timer->next = t; /* 设置链表的下一项 */
timerctl.next = timer->timeout;
io_store_eflags(e);
return;
}
/* 另一种情况 */
for (;;) {
s = t;
t = t->next;
if (t == 0) {
break; /* 没有下一个了 */
}
if (timer->timeout <= t->timeout) {
/* 找到合适的位置,s保留上一个,t保留下一个 */
s->next = timer; /* 设置 */
timer->next = t; /* timer */
io_store_eflags(e);
return;
}
}
/* 没有两个中间合适 */
s->next = timer;
timer->next = 0;
io_store_eflags(e);
return;
}
添加一个哨兵
用来简化程序
c
void init_pit(void)
{
int i;
struct TIMER *t;
io_out8(PIT_CTRL, 0x34);
io_out8(PIT_CNT0, 0x9c);
io_out8(PIT_CNT0, 0x2e);
timerctl.count = 0;
for (i = 0; i < MAX_TIMER; i++) {
timerctl.timers0[i].flags = 0; /* 所有的都设置为没有使用 */
}
t = timer_alloc(); /* 申请哨兵 */
t->timeout = 0xffffffff;
t->flags = TIMER_FLAGS_USING;
t->next = 0; /* 没有下一个 */
timerctl.t0 = t; /* 设置第一个是哨兵 */
timerctl.next = 0xffffffff; /* 设置时刻为最大值 */
return;
}