protothread 用法示例
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include "pt.h"
static struct pt codelock_pt, input_pt;
static const char code[4] = {'1', '4', '2', '3'};
static char key_pressed_flag;
static char pass_code[4] = {0};
static char pass_code_index;
struct timer {
int start;
int interval;
};
static struct timer codelock_timer, input_timer;
static int key_pressed()
{
if (key_pressed_flag != 0) {
key_pressed_flag = 0;
return 1;
}
return 0;
}
static int clock_time()
{
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
static void timer_set(struct timer *t, int interval)
{
t->interval = interval;
t->start = clock_time();
}
static int timer_expired(struct timer *t)
{
return (int)(clock_time() - t->start) >= (int)t->interval;
}
static PT_THREAD(codelock_thread(struct pt *pt))
{
static int keys;
PT_BEGIN(pt);
while(1) {
for (keys=0; keys < sizeof(code); ++keys) {
if (keys == 0)
PT_WAIT_UNTIL(pt, key_pressed());
else {
timer_set(&codelock_timer, 1000);
PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));
if (timer_expired(&codelock_timer)) {
pass_code_index = 0;
printf("Code lock timer expired \n");
break;
}
}
}
if (keys == sizeof(code)) {
printf("Correct code entered, waiting for 500 ms before unlocking \n");
timer_set(&codelock_timer, 500);
PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));
printf("code is: ");
for (keys=0; keys < sizeof(code); ++keys)
printf("'%c' ", code[keys]);
printf("\n");
printf("pass_code is: ");
for (keys=0; keys < sizeof(code); ++keys)
printf("'%c' ", pass_code[keys]);
printf("\n");
if (!timer_expired(&codelock_timer))
printf("Key pressed during final wait, code lock locked again \n");
else {
if (memcmp(pass_code, code, sizeof(code)) == 0) {
printf("Code lock unlocked \n");
PT_EXIT(pt);
}
printf("Code error, Try again \n");
pass_code_index = 0;
}
}
}
PT_END(pt);
}
static void press_key(char k)
{
printf("--- Key '%c' pressed \n", k);
pass_code[pass_code_index] = k;
pass_code_index = (pass_code_index + 1) % 4;
key_pressed_flag = 1;
}
static PT_THREAD(input_thread(struct pt *pt))
{
PT_BEGIN(pt);
printf("Waiting 1 second before entering first key \n");
timer_set(&input_timer, 1000);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('1');
timer_set(&input_timer, 100);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('2');
timer_set(&input_timer, 100);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('3');
timer_set(&input_timer, 2000);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('1');
timer_set(&input_timer, 200);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('4');
timer_set(&input_timer, 200);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('2');
timer_set(&input_timer, 2000);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('3');
timer_set(&input_timer, 200);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('1');
timer_set(&input_timer, 200);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('4');
timer_set(&input_timer, 200);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('2');
timer_set(&input_timer, 100);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('3');
timer_set(&input_timer, 100);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('4');
timer_set(&input_timer, 1500);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('1');
timer_set(&input_timer, 300);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('4');
timer_set(&input_timer, 400);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('2');
timer_set(&input_timer, 500);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('8');
timer_set(&input_timer, 2000);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('1');
timer_set(&input_timer, 300);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('4');
timer_set(&input_timer, 400);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('2');
timer_set(&input_timer, 500);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
press_key('3');
timer_set(&input_timer, 2000);
PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
PT_END(pt);
}
int main()
{
//初始化 2 個 protothread 的控制結構體
PT_INIT(&input_pt);
PT_INIT(&codelock_pt);
//調度 2 個 protothread, 直到 codelock_thread 退出
while(PT_SCHEDULE(codelock_thread(&codelock_pt))) {
PT_SCHEDULE(input_thread(&input_pt));
usleep(10);
}
return 0;
}