|
|
@ -149,7 +149,12 @@ struct trapframe switchk2u, *switchu2k; |
|
|
|
/* trap_dispatch - dispatch based on what type of trap occurred */ |
|
|
|
static void |
|
|
|
trap_dispatch(struct trapframe *tf) { |
|
|
|
char c; |
|
|
|
volatile char c; |
|
|
|
// 有限状态机? |
|
|
|
static enum {STARTED=0, STOPPED=1, WAITING_FOR_INPUT, READY_TO_OUTPUT} state = STOPPED; |
|
|
|
// 唉不能long long,看来很有可能会溢出啊 |
|
|
|
static long milliseconds = 0; |
|
|
|
static enum {COUNTDOWN=-1, COUNTUP=1} mode = COUNTUP; |
|
|
|
|
|
|
|
switch (tf->tf_trapno) { |
|
|
|
case IRQ_OFFSET + IRQ_TIMER: |
|
|
@ -159,10 +164,27 @@ trap_dispatch(struct trapframe *tf) { |
|
|
|
* (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks(). |
|
|
|
* (3) Too Simple? Yes, I think so! |
|
|
|
*/ |
|
|
|
ticks ++; |
|
|
|
if (ticks % TICK_NUM == 0) { |
|
|
|
print_ticks(); |
|
|
|
switch (state) { |
|
|
|
case STARTED: |
|
|
|
milliseconds += mode; |
|
|
|
// 当时间倒计时到0时转成停止状态 |
|
|
|
// 而正计时加了mode之后至少为1所以不会转换状态 |
|
|
|
// 使用小于等于0而不是等于0是为了防止万一出现异常导致小于0的情况 |
|
|
|
state = READY_TO_OUTPUT * (milliseconds <= 0); // 为了减少分支才写成这样 |
|
|
|
break; |
|
|
|
case READY_TO_OUTPUT: |
|
|
|
state = STOPPED; |
|
|
|
mode = COUNTUP; |
|
|
|
if (milliseconds < 0) milliseconds = 0; // 防止出现异常小于0 |
|
|
|
cprintf(MSG_COUNTDOWN_STOP); |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
ticks ++; |
|
|
|
// if (ticks % TICK_NUM == 0) { |
|
|
|
// print_ticks(); |
|
|
|
// } |
|
|
|
break; |
|
|
|
case IRQ_OFFSET + IRQ_COM1: |
|
|
|
c = cons_getc(); |
|
|
@ -170,7 +192,58 @@ trap_dispatch(struct trapframe *tf) { |
|
|
|
break; |
|
|
|
case IRQ_OFFSET + IRQ_KBD: |
|
|
|
c = cons_getc(); |
|
|
|
cprintf("kbd [%03d] %c\n", c, c); |
|
|
|
if (state == WAITING_FOR_INPUT) { |
|
|
|
long seconds = milliseconds / 1000; |
|
|
|
// if (c != '\0') cprintf("%c", c); |
|
|
|
// 如果是正在输入状态,此时不能键入字母或其他各种字符 |
|
|
|
// 在这里不能直接break不然就直接跳出中断处理程序了 |
|
|
|
// 所以用c=0来防止执行后面的转换状态 |
|
|
|
if (c == '\b' || c == '\n' || ('0' <= c && c <= '9')) { |
|
|
|
cprintf("%c", c); |
|
|
|
} else { |
|
|
|
c = '\0'; |
|
|
|
} |
|
|
|
if (c == '\b') { |
|
|
|
seconds /= 10; |
|
|
|
} |
|
|
|
if ('0' <= c && c <= '9') { |
|
|
|
seconds *= 10; |
|
|
|
seconds += c - '0'; |
|
|
|
} |
|
|
|
milliseconds = seconds * 1000; |
|
|
|
if (c == '\n') { |
|
|
|
state = STARTED; |
|
|
|
} |
|
|
|
c = '\0'; // 如果是正在输入状态,此时不能根据字母转换状态 |
|
|
|
} |
|
|
|
switch (c) { |
|
|
|
case 'a': |
|
|
|
mode = COUNTUP; |
|
|
|
cprintf(MSG_COUNTUP_START); |
|
|
|
break; |
|
|
|
case 'b': |
|
|
|
mode = COUNTDOWN; |
|
|
|
cprintf(MSG_COUNTDOWN_START); |
|
|
|
state = WAITING_FOR_INPUT; |
|
|
|
break; |
|
|
|
case 's': |
|
|
|
case 'c': |
|
|
|
state = STARTED; |
|
|
|
cprintf(MSG_START); |
|
|
|
break; |
|
|
|
case 'p': |
|
|
|
state = STOPPED; |
|
|
|
cprintf(MSG_PAUSE, milliseconds / 1000, milliseconds % 1000); |
|
|
|
break; |
|
|
|
case 'e': |
|
|
|
state = STOPPED; |
|
|
|
cprintf(MSG_STOP, milliseconds / 1000, milliseconds % 1000); |
|
|
|
milliseconds = 0; |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
// cprintf("kbd [%03d] %c\n", c, c); |
|
|
|
break; |
|
|
|
//LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes. |
|
|
|
case T_SWITCH_TOU: |
|
|
|