/unsupported/trunk/uiuc/pong/pong.c |
---|
0,0 → 1,602 |
////////////////////////////////////////////////////////////////// |
// Pong |
// Written for CS 324, UIUC |
// Spencer Hoke |
// James Kim |
// Tao Luo |
// |
// Last Modified: April 29, 2004 |
#include "pong.h" |
/////////////////////////////////////// |
// sets initial values of global variables |
void setglobals() { |
P_MASS = 100; |
kp = 30; |
kd = 20; // > sqrt(4*(XMAX - XMIN)* kp) |
AI_VIEWING_RANGE = 250; // window = YMAX - this |
balllist = NULL; |
num_balls = 0; // number of balls currently in system |
min_balls = 0; // minimum number of balls in the system |
locked = 0; // 1 if #balls kept constant |
ball_spd = 5; // ballspeed (default = 5) |
p_speed = 10; // # pixels to move each keypress |
p1_length = 150; // size of the paddles |
p2_length = 75; // size of the paddles |
p1_pos = (XMAX + XMIN - p1_length)/2; // initialize starting paddle positions |
p2_pos = (XMAX + XMIN - p2_length)/2; |
p2_target_pos = p2_pos; // initially no movement |
points1 = 0; // scores for each side |
points2 = 0; |
} |
/////////////////////////////////////// |
// center at (x,y) with radius RAD and color c |
void draw_ball(int x, int y, int c) { |
mutex_lock(&draw_mutex); |
grx_disc(x, y, RAD, c); |
mutex_unlock(&draw_mutex); |
} |
/////////////////////////////////////// |
// top left corner is (x,y), length is l, |
// thickness is P_THICKNESS, and color is c |
void draw_paddle(int x, int y, int l, int c) { |
mutex_lock(&draw_mutex); |
grx_box(x, y, x + l, y + P_THICKNESS, c); |
mutex_unlock(&draw_mutex); |
} |
/////////////////////////////////////// |
// draws a line where the computer's viewing window starts |
void draw_viewwin(int col) { |
mutex_lock(&draw_mutex); |
grx_line(XMIN-RAD, AI_VIEWING_RANGE+YMIN, XMAX+RAD, AI_VIEWING_RANGE+YMIN, col); |
mutex_unlock(&draw_mutex); |
} |
/////////////////////////////////////// |
void print_scores() { |
char st1[15], st2[15]; |
sprintf(st1, "Player 1:%6d", points1); |
sprintf(st2, "Player 2:%6d", points2); |
mutex_lock(&draw_mutex); |
grx_text(st1, XMIN-RAD-1, 20, blue, black); |
grx_text(st2, XMIN-RAD-1, 30, red, black); |
mutex_unlock(&draw_mutex); |
} |
/////////////////////////////////////// |
void print_numballs() { |
char st[15]; |
sprintf(st, "Num balls:%3d", num_balls); |
mutex_lock(&draw_mutex); |
grx_text(st, XMAX-100, 20, magenta, black); |
mutex_unlock(&draw_mutex); |
} |
/////////////////////////////////////// |
void print_constants() { |
char st[15]; |
sprintf(st, "kp:%3d, kd:%3d, mass:%4d", kp, kd, P_MASS); |
mutex_lock(&draw_mutex); |
grx_text(st, XMIN-RAD-1, YMAX+20, magenta, black); |
mutex_unlock(&draw_mutex); |
} |
/////////////////////////////////////// |
TASK ball(void *arg) { |
int x, y; // current position |
int oldx, oldy; // last position |
int dx, dy; // delta x, y |
int theta, col; |
double r; // theta in radians |
int p1len, p2len, p1pos, p2pos; // temp storage of length and position |
int outx; |
int hitp1, hitp2; // 1 if ball has hit paddle |
int in1, in2; // 1 if ball is currently inside paddle (error) |
struct ballinfo myinfo; // shared x/y/theta |
myinfo.x = x = oldx = XMIN; // start in middle of the left |
myinfo.y = y = oldy = (YMIN+YMAX)/2; |
col = rand()%14 + 2; // color ball |
// insert myinfo into global list |
mutex_lock(&list_mutex); |
if(balllist != NULL) // update old first entry in list |
balllist->prev = &myinfo; |
myinfo.next = balllist; |
myinfo.prev = NULL; |
balllist = &myinfo; |
mutex_unlock(&list_mutex); |
// starting angle = [ANGMIN,ANGMAX] |
theta = rand()%(ANGMAX - ANGMIN) + ANGMIN; |
if (rand()%2 == 1) // random starting direction |
theta *= -1; |
if (theta > 360) theta -= 360; |
if (theta < 0) theta += 360; |
myinfo.theta = theta; |
r = (double)theta * PI / 180.; |
while (1) { |
dx = (float)(ball_spd * cos(r)); |
dy = (float)(ball_spd * sin(r)); |
x += dx; |
y += dy; |
// check boundary conditions |
if (y >= YMAX) { // end task and score point for player 2 |
points1++; |
break; |
} |
if (y <= YMIN) { // end task and score point for player 1 |
points2++; |
break; |
} |
p1len = p1_length; // copy globals |
p1pos = p1_pos; |
p2len = p2_length; |
p2pos = p2_pos; |
outx = (x >= XMAX) || (x <= XMIN); |
hitp1 = (y <= (YMIN + 2*RAD + P_THICKNESS)) // y is within range of paddle |
&& (x >= (p1pos - RAD)) && (x <= (p1pos + p1len + RAD)); // x is within range of paddle |
hitp2 = (y >= (YMAX - 2*RAD - P_THICKNESS)) // y is within range of paddle |
&& (x >= (p2pos - RAD)) && (x <= (p2pos + p2len + RAD)); // x is within range of paddle |
// need these in case ball goes in the side of the paddle |
in1 = (oldy <= (YMIN + 2*RAD + P_THICKNESS)) // oldy is within range of paddle |
&& (oldx >= (p1pos - RAD)) && (oldx <= (p1pos + p1len + RAD)); // oldx is within range of paddle |
in2 = (oldy >= (YMAX - 2*RAD - P_THICKNESS)) // oldy is within range of paddle |
&& (oldx >= (p2pos - RAD)) && (oldx <= (p2pos + p2len + RAD)); // oldx is within range of paddle |
if (outx || ((hitp1 || hitp2) && !in1 && !in2)) { // ball needs to bounce |
x -= dx; |
y -= dy; |
if (outx) theta = 180 - theta; // bounce off wall |
if ((hitp1 || hitp2) && !in1 && !in2) theta = -theta; // bounce off paddle |
if (theta > 360) theta -= 360; |
else if (theta < 0) theta += 360; |
r = (double)theta * PI / 180.; |
x += (float)(ball_spd * cos(r)); |
y += (float)(ball_spd * sin(r)); |
} |
draw_ball(oldx, oldy, black); // clear old position |
draw_ball(x, y, col); // draw new ball |
oldx = x; oldy = y; |
mutex_lock(&list_mutex); // updates values in list |
myinfo.x = x; |
myinfo.y = y; |
myinfo.theta = theta; |
mutex_unlock(&list_mutex); |
task_endcycle(); |
} |
// remove myinfo from list |
mutex_lock(&list_mutex); |
if(myinfo.next != NULL) |
(myinfo.next)->prev = myinfo.prev; |
if(myinfo.prev != NULL) |
(myinfo.prev)->next = myinfo.next; |
else |
balllist = myinfo.next; |
mutex_unlock(&list_mutex); |
draw_ball(oldx, oldy, 0); // clear ball |
print_scores(); // update score |
num_balls--; // remove ball from system |
if(!locked) |
print_numballs(); // update count of balls |
return NULL; |
} |
/////////////////////////////////////// |
void addball() { |
HARD_TASK_MODEL m; |
PID pid; |
hard_task_default_model(m); |
hard_task_def_ctrl_jet (m); |
hard_task_def_wcet (m, BALL_WCET); |
hard_task_def_mit (m, BALL_PER); |
hard_task_def_group (m, BALLGROUP); |
hard_task_def_usemath (m); |
pid = task_create("ball", ball, &m, NULL); |
if (pid == NIL) { |
grx_close(); |
sys_shutdown_message("Could not create task <ball> errno=%d", errno); |
sys_abort(errno); |
} |
task_activate(pid); |
num_balls++; |
print_numballs(); |
} |
/////////////////////////////////////// |
// paddle 1 controller |
TASK paddle1(void *arg) { |
int oldpos, newpos; |
int move, oldlength, length; |
oldpos = newpos = p1_pos; |
oldlength = -1; // force draw initially |
while (1) { |
length = p1_length; // need to copy in case they change |
move = p1_move; |
p1_move -= move; // update global variable |
// get new position of ball |
newpos += move * p_speed; |
if(newpos < XMIN) // tried to move too far right |
newpos = XMIN; |
else if(newpos > (XMAX - length)) // tried to move too far left |
newpos = XMAX - length; |
if ((newpos != oldpos) || (length != oldlength)) { // need to redraw the paddle |
p1_pos = newpos; // update global position |
draw_paddle(oldpos, YMIN + RAD, oldlength, black); // clear old paddle |
draw_paddle(newpos, YMIN + RAD, length, blue); // draw new one |
oldpos = newpos; |
oldlength = length; |
} |
else |
draw_paddle(newpos, YMIN + RAD, length, blue); // refresh paddle |
task_endcycle(); |
} |
} |
/////////////////////////////////////// |
// determines target position of paddle 2 |
TASK p2ai(void *arg) { |
int proj; // projected length to y-value of paddle |
int closestBallY_Location = 0; |
int closestBallX_Location = 0; |
int closestBallY_Angle = 0; |
int closestToPaddle; |
int projectedX_Location = 0; |
int foundBall; |
double r; // angle in radians |
struct ballinfo *cur; |
char st[20]; |
while(1) { |
if (num_balls != 0) { // if there are balls |
//finds the closest ball and its position and angle |
closestBallY_Location = AI_VIEWING_RANGE + YMIN; |
closestToPaddle = 1000000; // large default number |
foundBall = 0; |
mutex_lock(&list_mutex); |
for (cur = balllist; cur != NULL; cur = cur->next) { |
if (cur->y > closestBallY_Location // within window |
&& cur->y < (YMAX - RAD - P_THICKNESS) // not past paddle already |
&& cur->theta < 180) // going toward paddle |
{ |
r = (double)(cur->theta) * PI / 180.; |
proj = (float)( (YMAX - RAD - P_THICKNESS - cur->y) / sin(r) ); // geometry |
if(proj < closestToPaddle) { // this is the closest one |
foundBall = 1; |
closestBallY_Location = cur->y; |
closestBallX_Location = cur->x; |
closestBallY_Angle = cur->theta; |
closestToPaddle = proj; |
} |
} |
} |
mutex_unlock(&list_mutex); |
//finds where it needs to move to |
if (foundBall == 1) { |
r = (double)closestBallY_Angle * PI / 180.; |
projectedX_Location = (float)( (YMAX - RAD - P_THICKNESS - closestBallY_Location) / tan(r) ); // geometry |
projectedX_Location += closestBallX_Location; |
while(projectedX_Location < XMIN || projectedX_Location > XMAX) { // adjust for ball bounces |
if(projectedX_Location < XMIN) |
projectedX_Location = 2*XMIN - projectedX_Location; // bounce off left side |
if(projectedX_Location > XMAX) |
projectedX_Location = 2*XMAX - projectedX_Location; // bounce off right side |
} |
sprintf(st, "Proj X: %3d", projectedX_Location); |
mutex_lock(&draw_mutex); |
grx_text(st, XMAX-85, YMAX+20, magenta, black); |
mutex_unlock(&draw_mutex); |
p2_target_pos = projectedX_Location - p2_length/2; // copy into target for p2 |
} |
} |
task_endcycle(); |
} |
} |
/////////////////////////////////////// |
// paddle 2 controller - applies forces and draws paddle |
TASK paddle2(void *arg) { |
int oldpos, newpos; |
int positionErrorX, oldlength, length; |
int force = 0, acceleration = 0, velocity = 0; // paddle movement |
oldpos = newpos = p2_pos; |
oldlength = -1; // force draw initially |
while (1) { |
length = p2_length; // need to copy in case they change |
positionErrorX = p2_target_pos - oldpos; |
//Applying force |
force = kp * positionErrorX - kd * velocity; |
acceleration = force / P_MASS; |
velocity += acceleration; // new velocity |
newpos = oldpos + velocity; // using new velocity, so incorporates acceleration |
if(newpos < XMIN) // tried to move too far right |
newpos = XMIN; |
else if(newpos > (XMAX - length)) // tried to move too far left |
newpos = XMAX - length; |
if ((newpos != oldpos) || (length != oldlength)) { // need to redraw the paddle |
p2_pos = newpos; // update global position |
draw_paddle(oldpos, YMAX - P_THICKNESS - RAD, oldlength, black); // clear old paddle |
draw_paddle(newpos, YMAX - P_THICKNESS - RAD, length, red); // draw new one |
oldpos = newpos; |
oldlength = length; |
} |
else |
draw_paddle(newpos, YMAX - P_THICKNESS - RAD, length, red); // refresh paddle |
task_endcycle(); |
} |
} |
/////////////////////////////////////// |
TASK countmon(void *arg) { |
while(1) { |
while(num_balls < min_balls) |
addball(); |
task_endcycle(); |
} |
} |
/////////////////////////////////////// |
// called when the system exits |
void byebye(void *arg) { |
grx_close(); |
cprintf("Thanks for playing!\n"); |
} |
/////////////////////////////////////// |
int main(int argc, char **argv) { |
HARD_TASK_MODEL m; |
PID pid; |
char c; |
TIME seme; // used to init the random seed |
PI_mutexattr_t a; // for PI mutex init |
// Set the closing function |
sys_atrunlevel(byebye, NULL, RUNLEVEL_BEFORE_EXIT); |
// initialize global variables |
setglobals(); |
// initialize PI mutexes |
PI_mutexattr_default(a); |
mutex_init(&draw_mutex, &a); |
mutex_init(&list_mutex, &a); |
// graphic card Initialization |
if (grx_init() < 1) { |
sys_abort(errno); |
} |
if (grx_open(640, 480, 8) < 0) { |
cprintf("GRX Error\n"); |
sys_abort(errno); |
} |
// Draw initial screen layout and menu |
grx_rect(XMIN-RAD-1, YMIN-RAD-1, XMAX+RAD+1, YMAX+RAD+1, yellow); |
grx_text("Scores:", XMIN-RAD-1, 10, magenta, black); |
grx_text("PONG", XMENU, YMENU, magenta, black); |
grx_text("Create a ball: SPACE", XMENU, YMENU+15, redorange, black); |
grx_text("Quit program: ESC", XMENU, YMENU+25, redorange, black); |
grx_text("Move top paddle: z x", XMENU, YMENU+35, redorange, black); |
grx_text("Change top size: a s", XMENU, YMENU+45, redorange, black); |
grx_text("Change bottom size: q w", XMENU, YMENU+55, redorange, black); |
grx_text("Keep # Balls Const: l", XMENU, YMENU+65, redorange, black); |
grx_text("Change ball speed: 1 2", XMENU, YMENU+75, redorange, black); |
grx_text("Change kp: 3 4", XMENU, YMENU+85, redorange, black); |
grx_text("Change kd: 5 6", XMENU, YMENU+95, redorange, black); |
grx_text("Change mass: 7 8", XMENU, YMENU+105, redorange, black); |
grx_text("Change AI window: 9 0", XMENU, YMENU+115, redorange, black); |
print_scores(); |
print_numballs(); |
print_constants(); |
draw_viewwin(gray); |
// randomize for ball starting angle |
seme = sys_gettime(NULL); |
srand(seme); |
// set up the paddle tasks |
hard_task_default_model(m); |
hard_task_def_ctrl_jet (m); |
hard_task_def_wcet (m, P_WCET); |
hard_task_def_mit (m, P_PER); |
hard_task_def_group (m, PGROUP); |
hard_task_def_usemath (m); |
pid = task_create("paddle1", paddle1, &m, NULL); |
if (pid == NIL) { |
grx_close(); |
sys_shutdown_message("Could not create task <paddle1> errno=%d", errno); |
sys_abort(errno); |
} |
hard_task_default_model(m); |
hard_task_def_ctrl_jet (m); |
hard_task_def_wcet (m, P_WCET); |
hard_task_def_mit (m, P_PER); |
hard_task_def_group (m, PGROUP); |
hard_task_def_usemath (m); |
pid = task_create("p2ai", p2ai, &m, NULL); |
if (pid == NIL) { |
grx_close(); |
sys_shutdown_message("Could not create task <p2ai> errno=%d", errno); |
sys_abort(errno); |
} |
hard_task_default_model(m); |
hard_task_def_ctrl_jet (m); |
hard_task_def_wcet (m, P_WCET); |
hard_task_def_mit (m, P_PER); |
hard_task_def_group (m, PGROUP); |
hard_task_def_usemath (m); |
pid = task_create("paddle2", paddle2, &m, NULL); |
if (pid == NIL) { |
grx_close(); |
sys_shutdown_message("Could not create task <paddle2> errno=%d", errno); |
sys_abort(errno); |
} |
group_activate(PGROUP); |
#ifdef JET_ON |
scenario_jetcontrol(); |
init_jetcontrol(); |
group_activate(JET_GROUP); |
#endif |
hard_task_default_model(m); |
hard_task_def_ctrl_jet (m); |
hard_task_def_wcet (m, BALL_WCET); |
hard_task_def_mit (m, BALL_PER); |
hard_task_def_group (m, BALLGROUP); |
hard_task_def_usemath (m); |
pid = task_create("countmon", countmon, &m, NULL); |
if (pid == NIL) { |
grx_close(); |
sys_shutdown_message("Could not create task <countmonitor> errno=%d", errno); |
sys_abort(errno); |
} |
task_activate(pid); |
while(1) { // read in commands ( exit handled in handle_key() ) |
c = keyb_getch(BLOCK); |
switch (c) { |
case ESC: // quit program |
sys_abort(0); |
break; |
case ' ': // create a new ball |
addball(); |
if(locked == 1) // update min # balls if locked |
min_balls++; |
break; |
case 'z': // move paddle1 left |
p1_move--; |
break; |
case 'x': // move paddle1 right |
p1_move++; |
break; |
case 's': // increase paddle1 length |
if (p1_length < (XMAX - XMIN - P_DLENGTH)) |
p1_length += P_DLENGTH; |
break; |
case 'a': // decrease paddle1 length |
if (p1_length > (1 + P_DLENGTH)) |
p1_length -= P_DLENGTH; |
break; |
case 'w': // increase paddle2 length |
if (p2_length < (XMAX - XMIN - P_DLENGTH)) |
p2_length += P_DLENGTH; |
break; |
case 'q': // decrease paddle2 length |
if (p2_length > (1 + P_DLENGTH)) |
p2_length -= P_DLENGTH; |
break; |
case 'l': // lock number of balls |
if((locked = !locked)) { |
min_balls = num_balls; |
mutex_lock(&draw_mutex); |
grx_text(" Locked", XMAX-100, 30, redorange, black); |
mutex_unlock(&draw_mutex); |
} |
else { |
min_balls = 0; |
mutex_lock(&draw_mutex); |
grx_text(" ", XMAX-100, 30, redorange, black); |
mutex_unlock(&draw_mutex); |
} |
break; |
case '1': // decrease ball speed |
ball_spd--; |
break; |
case '2': // increase ball speed |
ball_spd++; |
break; |
case '3': // decrease kp |
if(kp > 0) |
kp--; |
print_constants(); |
break; |
case '4': // increase kp |
kp++; |
print_constants(); |
break; |
case '5': // decrease kd |
if(kd > 0) |
kd--; |
print_constants(); |
break; |
case '6': // increase kd |
kd++; |
print_constants(); |
break; |
case '7': // decrease mass |
if(P_MASS > 5) |
P_MASS -= 5; |
print_constants(); |
break; |
case '8': // increase mass |
P_MASS += 5; |
print_constants(); |
break; |
case '9': // decrease AI window |
draw_viewwin(black); // clear old line |
AI_VIEWING_RANGE += 5; |
draw_viewwin(gray); // draw new one |
break; |
case '0': // increase AI window |
draw_viewwin(black); // clear old line |
AI_VIEWING_RANGE -= 5; |
draw_viewwin(gray); // draw new one |
break; |
default: |
break; |
} |
} |
return 0; |
} |
/unsupported/trunk/uiuc/pong/initfile.c |
---|
0,0 → 1,85 |
////////////////////////////////////////////////////////////////// |
// Pong |
// Written for CS 324, UIUC |
// Spencer Hoke |
// James Kim |
// Tao Luo |
// |
// Last Modified: April 29, 2004 |
// |
// System initialization file |
// |
// This file contains the 2 functions needed to initialize the system. |
// |
// These functions register the following levels: |
// |
// an EDF (Earliest Deadline First) level |
// a RR (Round Robin) level |
// a CBS (Costant Bandwidth Server) level |
// a Dummy level |
// |
// It can accept these task models: |
// |
// HARD_TASK_MODEL (wcet+mit) at level 0 |
// SOFT_TASK_MODEL (met, period) at level 1 |
// NRT_TASK_MODEL at level 2 |
// |
// This file is similar to the configuration of in demos/base |
// |
// TICK is set to 0 (one-shot timer is used) |
#include "kernel/kern.h" |
#include "modules/edf.h" |
#include "modules/cbs.h" |
#include "modules/rr.h" |
#include "modules/dummy.h" |
#include "modules/sem.h" |
#include "modules/hartport.h" |
#include "modules/cabs.h" |
#include "modules/pi.h" |
#include "drivers/keyb.h" |
// sysyem tick in us |
#define TICK 0 |
/*+ RR tick in us +*/ |
//#define RRTICK 10000 |
#define RRTICK 2000 |
TIME __kernel_register_levels__(void *arg) |
{ |
struct multiboot_info *mb = (struct multiboot_info *)arg; |
EDF_register_level(EDF_ENABLE_WCET_CHECK); |
CBS_register_level(CBS_ENABLE_ALL, 0); |
RR_register_level(RRTICK, RR_MAIN_YES, mb); |
dummy_register_level(); |
SEM_register_module(); // needed for keyboard |
CABS_register_module(); |
PI_register_module(); |
return TICK; |
} |
TASK __init__(void *arg) |
{ |
struct multiboot_info *mb = (struct multiboot_info *)arg; |
KEYB_PARMS kparms = BASE_KEYB; |
HARTPORT_init(); |
keyb_def_ctrlC(kparms, NULL); |
keyb_def_map(kparms,itaMap); |
KEYB_init(&kparms); |
__call_main__(mb); |
return (void *)0; |
} |
/unsupported/trunk/uiuc/pong/readme.pj |
---|
0,0 → 1,9 |
Hi! |
This is a really nice pong demo written in the University of UIUC, USA! |
The demo has been reported working on Shark 1.22. |
bye |
PJ |
/unsupported/trunk/uiuc/pong/jetctrl.c |
---|
0,0 → 1,197 |
////////////////////////////////////////////////////////////////// |
// Pong |
// Written for CS 324, UIUC |
// Spencer Hoke |
// James Kim |
// Tao Luo |
// |
// Last Modified: April 29, 2004 |
#include "pong.h" |
/////////////////////////////////////// |
TASK jetdummy_task(void *arg) |
{ |
TIME now_dummy, last_dummy, diff_dummy, slice; |
struct timespec now, last, diff; |
int x = 0; |
int height; |
NULL_TIMESPEC(&last); |
last_dummy = 0; |
for (;;) { |
task_nopreempt(); |
jet_getstat(DUMMY_PID, NULL, NULL, NULL, &now_dummy); |
sys_gettime(&now); |
task_preempt(); |
SUBTIMESPEC(&now, &last, &diff); |
slice = diff.tv_sec * 1000000 + diff.tv_nsec/1000; |
diff_dummy = now_dummy - last_dummy; |
height = (int)(JET_DUMMY_HEIGHT*((float)diff_dummy)/((float)slice)); |
TIMESPEC_ASSIGN(&last, &now); |
last_dummy = now_dummy; |
mutex_lock(&draw_mutex); |
grx_line(JET_DUMMY_X+x,JET_DUMMY_Y, |
JET_DUMMY_X+x,JET_DUMMY_Y+height ,black); |
grx_line(JET_DUMMY_X+x,JET_DUMMY_Y+height, |
JET_DUMMY_X+x,JET_DUMMY_Y+JET_DUMMY_HEIGHT,white); |
grx_line(JET_DUMMY_X+(x+1)%JET_DUMMY_WIDTH,JET_DUMMY_Y, |
JET_DUMMY_X+(x+1)%JET_DUMMY_WIDTH,JET_DUMMY_Y+JET_DUMMY_HEIGHT,blue); |
mutex_unlock(&draw_mutex); |
x = (x+1)%JET_DUMMY_WIDTH; |
task_endcycle(); |
} |
} |
/////////////////////////////////////// |
TASK jetctrl_task(void *arg) |
{ |
char st[50]; |
TIME sum, max; |
int n; |
PID i; |
int printed = 0; |
for (;;) { |
for (i=2, printed=0; i<MAX_PROC && printed<JET_NTASK; i++) { |
if (jet_getstat(i, &sum, &max, &n, NULL) != -1) { |
if (!n) n=1; |
sprintf(st, " %4d %4d %s", (int)sum/n, (int)max, proc_table[i].name); |
mutex_lock(&draw_mutex); |
grx_text(st, JET_DUMMY_X-45, JET_Y_NAME+16+printed*8, gray, black); |
mutex_unlock(&draw_mutex); |
printed++; |
} |
} |
while (printed < JET_NTASK) { |
mutex_lock(&draw_mutex); |
grx_text(" ", JET_DUMMY_X-45, JET_Y_NAME+16+printed*8, gray, black); |
mutex_unlock(&draw_mutex); |
printed++; |
} |
task_endcycle(); |
} |
} |
/////////////////////////////////////// |
TASK jetslide_task(void *arg) |
{ |
TIME sum, curr, max; |
TIME total[JET_NTASK]; |
int slides[JET_NTASK]; |
PID i; |
int printed = 0; |
for (;;) { |
// Fill the total array in a nonpreemptive section |
task_nopreempt(); |
for (i=2, printed=0; i<MAX_PROC && printed<JET_NTASK; i++) { |
if (jet_getstat(i, &sum, NULL, NULL, &curr) != -1) { |
total[printed] = sum+curr; |
printed++; |
} |
} |
task_preempt(); |
while (printed < JET_NTASK) |
total[printed++] = 0; |
// Compute the Max elapsed time |
max = 0; |
for (i=0; i<JET_NTASK; i++) |
if (total[i] > max) max = total[i]; |
if (!max) max = 1; |
// Compute the slides width |
for (i=0; i<JET_NTASK; i++) |
slides[i] = (int)( (((float)total[i])/max) * JET_SLIDE_WIDTH); |
// print the data |
mutex_lock(&draw_mutex); |
for (i=0; i<JET_NTASK; i++) { |
grx_box(JET_SLIDE_X, JET_Y_NAME+16+i*8, |
JET_SLIDE_X+slides[i], JET_Y_NAME+23+i*8, gray); |
grx_box(JET_SLIDE_X+slides[i], JET_Y_NAME+16+i*8, |
JET_SLIDE_X+JET_SLIDE_WIDTH, JET_Y_NAME+23+i*8, black); |
} |
while (i<JET_NTASK) { |
grx_box(JET_SLIDE_X, JET_Y_NAME+16+i*8, |
JET_SLIDE_X+JET_SLIDE_WIDTH, JET_Y_NAME+20+i*8, black); |
i++; |
} |
mutex_unlock(&draw_mutex); |
task_endcycle(); |
} |
} |
/////////////////////////////////////// |
void scenario_jetcontrol(void) |
{ |
grx_line(JET_DUMMY_X-40,JET_DUMMY_Y-15,JET_DUMMY_X+200,JET_DUMMY_Y-15, redorange); |
grx_text("Mean Max Name Slide", JET_DUMMY_X-40, JET_Y_NAME, gray, black); |
grx_line(JET_DUMMY_X-40,JET_Y_NAME+10,JET_DUMMY_X+200,JET_Y_NAME+10,lime); |
grx_rect(JET_DUMMY_X-1, JET_DUMMY_Y-1, |
JET_DUMMY_X+JET_DUMMY_WIDTH, JET_DUMMY_Y+JET_DUMMY_HEIGHT+1, lime); |
grx_text("100%", JET_DUMMY_X-40, JET_DUMMY_Y, lime, black); |
grx_text(" 0%", JET_DUMMY_X-40, JET_DUMMY_Y+JET_DUMMY_HEIGHT-8, lime, black); |
} |
/////////////////////////////////////// |
void init_jetcontrol(void) |
{ |
SOFT_TASK_MODEL m3, m4, m5; |
PID p3, p4, p5; |
soft_task_default_model(m3); |
soft_task_def_level(m3,1); |
soft_task_def_period(m3, PERIOD_JETCTRL); |
soft_task_def_met(m3, WCET_JETCTRL); |
soft_task_def_ctrl_jet(m3); |
soft_task_def_group(m3, JET_GROUP); |
p3 = task_create("jctrl", jetctrl_task, &m3, NULL); |
if (p3 == -1) { |
grx_close(); |
sys_shutdown_message("Could not create task <jetcontrol> errno=%d", errno); |
sys_end(); |
} |
soft_task_default_model(m4); |
soft_task_def_level(m4,1); |
soft_task_def_period(m4, PERIOD_JETDUMMY); |
soft_task_def_met(m4, WCET_JETDUMMY); |
soft_task_def_group(m4, JET_GROUP); |
soft_task_def_usemath(m4); |
soft_task_def_ctrl_jet(m4); |
p4 = task_create("jdmy", jetdummy_task, &m4, NULL); |
if (p4 == -1) { |
grx_close(); |
sys_shutdown_message("Could not create task <jetdummy> errno=%d", errno); |
sys_end(); |
} |
soft_task_default_model(m5); |
soft_task_def_level(m5,1); |
soft_task_def_period(m5, PERIOD_JETSLIDE); |
soft_task_def_met(m5, WCET_JETSLIDE); |
soft_task_def_group(m5, JET_GROUP); |
soft_task_def_usemath(m5); |
soft_task_def_ctrl_jet(m5); |
p5 = task_create("jsli", jetslide_task, &m5, NULL); |
if (p5 == -1) { |
grx_close(); |
sys_shutdown_message("Could not create task <jetslide> errno=%d", errno); |
sys_end(); |
} |
} |
/unsupported/trunk/uiuc/pong/pong.h |
---|
0,0 → 1,129 |
////////////////////////////////////////////////////////////////// |
// Pong |
// Written for CS 324, UIUC |
// Spencer Hoke |
// James Kim |
// Tao Luo |
// |
// Last Modified: April 29, 2004 |
// |
// Initial values for global variables are |
// set in function setglobals() in pong.c |
#ifndef _PONG_H_ |
#define _PONG_H_ |
#include <kernel/kern.h> |
#include <kernel/func.h> |
#include <kernel/types.h> |
#include <kernel/descr.h> |
#include <drivers/glib.h> |
#include <drivers/keyb.h> |
#include <modules/pi.h> |
#include <stdlib.h> |
#include <ll/ll.h> |
#include <math.h> |
#define JET_ON |
#define JET_GROUP 3 |
#define WCET_JETCTRL 7500 |
#define WCET_JETDUMMY 200 |
#define WCET_JETSLIDE 2300 |
#define PERIOD_JETCTRL 100000 |
#define PERIOD_JETDUMMY 100000 |
#define PERIOD_JETSLIDE 100000 |
#define JET_NTASK 28 |
#define JET_Y_NAME 240 |
#define DUMMY_PID 1 |
#define JET_DUMMY_WIDTH 100 |
#define JET_DUMMY_HEIGHT 60 |
#define JET_DUMMY_X 390 |
#define JET_DUMMY_Y 160 |
#define JET_SLIDE_WIDTH 120 |
#define JET_SLIDE_X 510 |
#define black 0 // some colors for 8-bit graphics |
#define green 2 |
#define ltblue 3 |
#define red 4 |
#define purple 5 |
#define orange 6 |
#define gray 7 |
#define dkgray 8 |
#define blue 9 |
#define lime 10 |
#define bluegreen 11 |
#define redorange 12 |
#define magenta 13 |
#define yellow 14 |
#define white 15 |
void init_jetcontrol(); // init functions for jetcontrol |
void scenario_jetcontrol(); |
int P_MASS; // mass of the paddle, should be greater than kp because of how acceleration is implemented |
int kp; |
int kd; // > sqrt(4*(XMAX - XMIN)* kp) |
int AI_VIEWING_RANGE; // how close does the ball needs to be before the AI notices it |
#define MAX_BALLS 35 |
#define XMENU 350 // menu level |
#define YMENU 10 |
#define XMIN 14 // main window area |
#define XMAX 330 |
#define YMIN 50 |
#define YMAX 450 |
int num_balls; // number of balls currently in system |
int min_balls; // minimum number of balls in the system |
int locked; // 1 if #balls kept constant |
int ball_spd; // ballspeed (default = 5) |
#define ANGMAX 60 // max starting angle |
#define ANGMIN 15 // min starting angle |
#define RAD 3 // radius of balls |
//#define MAX_P 35 // max number of balls |
#define BALLGROUP 1 |
#define BALL_PER 40000 // task period |
#define BALL_WCET 750 // task wcet |
#define ESC 27 // ASCII code of ESCAPE key |
int p_speed; // # pixels to move each keypress |
#define P_THICKNESS 3 // pixel thickness of paddles |
#define P_DLENGTH 5 // delta length for paddles |
int p1_length; // size of the paddles |
int p2_length; // size of the paddles |
int p1_pos; // x position of left side of paddles |
int p2_pos; |
int p2_target_pos; // best position for paddle 2 |
int p1_move; // + to move right, - to move left |
#define PGROUP 2 |
#define P_PER 40000 |
#define P_WCET 250 |
int points1; // scores for each side |
int points2; |
mutex_t draw_mutex; // used for calls to grx functions |
mutex_t list_mutex; // used for balllist access |
typedef struct ballinfo{ |
int x, y, theta; |
struct ballinfo *prev; // double linked list |
struct ballinfo *next; |
} ballinfo; |
struct ballinfo *balllist; // head of list of balls |
#endif /* _PONG_H_ */ |
/unsupported/trunk/uiuc/pong/readme.txt |
---|
0,0 → 1,156 |
---------------------------------- |
Pong demo |
by |
Spencer Hoke |
James Kim |
Tao Luo |
for |
CS 324 Real-Time Systems |
at The University of Illinois at Urbana-Champaign |
with Marco Caccamo |
May 5, 2004 |
---------------------------------- |
FILES: |
MAKEFILE The makefile used to compile the application; |
PONG.H Header file containing constants used by both pong and JET |
PONG.C Main code |
JETCTRL.C Tasks for the JET monitors |
(This file is based on the jetctrl.c file from other Shark demos) |
INITFILE.C Initializes EDF/CBS scheduling and mutexes |
README.TXT This file |
USAGE: |
- Copy the source files into a folder within the shark/demos and use 'make' to |
compile. |
- Run by typing 'x pong' at the A:\> prompt if using the standard boot disk. |
PROGRAM OPERATION: |
- The purpose of each player is to control the paddle so that the balls bounce |
off the paddle and past the other player's paddle. |
- Adding new balls is done by pressing the space bar. |
- The number of balls can be kept constant by pressing the L key. "Locked" |
will be displayed under the number of balls indicating that the number of |
balls will be held constant at this number. The countMonitor task adds new |
balls whenever one leaves. When L is pressed again, balls that exit will not |
be reintroduced. |
- The scores for each player are shown in the upper left corner and are |
updated whenever a ball reaches the top or bottom of the play area. At this |
time, that ball is removed. |
- The difficulty of the computer's paddle can be changed by adjusting the |
length of each paddle, and constants controlled by keys 0-9. |
- You can adjust the length of the paddles or constants at any time. |
GRAPHICS: |
- It works at 640x480 8 bit colors using the grx interface |
- On the left is the main playing area. On the right are the commands and the |
JET information. Adjustable parameters are shown above and below the play |
area. |
TASKS: |
- Ball - each ball is a separate task. There can be as many of these as can be |
scheduled. Each one stores a position and angle, and updates with a new |
position each task cycle, drawing a black circle over its old position and |
drawing its new position. The balls also check to make sure that their new |
position is not outside the play area or inside of a paddle, in which case |
balls will bounce and change angles. If a ball goes past the paddle, it |
is removed and the task ends. Ball bounces are done elastically. |
- Paddle1 - this is the user-controlled paddle. It uses the keys entered by |
the user to update its position during each cycle. |
- Paddle2 - this is the computer-controlled paddle. It uses a position |
generated by task p2ai and moves toward a new position by applying both |
proportional and derivative forces. The paddle's mass and constants kp and |
kd are all adjustable at run-time. |
- P2ai - this task reads all the current balls in the system that are within |
the AI viewing window (adjustable at run-time) and determines the position |
that paddle2 should move to in order to hit the next ball. The first ball to |
hit is calculated based on the position and angles of the balls, and also |
accounts for bouncing |
- CountMonitor - if the number of balls is locked, this task checks to see if |
the number of balls in the system is at least equal to the min_balls |
variable and adds ball tasks if not. |
- JetCtrl - updates the table of tasks with their mean/max execution times |
- JetDummy - draws the system utilization graph |
- JetSlide - draws the utilization bars beside each task listed in the JET |
task list. |
- Main - after initialization, main reads the keyboard. Reads are blocking, |
and the appropriate action is taken after a key is pressed. |
TASK SCHEDULING: |
- Tasks are scheduled using EDF with a CBS. JET tasks are soft and follow |
CBS, while all other tasks are hard and follow EDF scheduling. Parameters for |
the tasks are (in ms): |
JetCtrl 7.5 met 100 period |
JetDummy 0.2 met 100 period |
JetSlide 2.1 met 100 period |
Balls 0.75 wcet 40 period |
CountMon 0.75 wcet 40 period |
Paddles 0.25 wcet 40 period |
P2ai 0.25 wcet 40 period |
- Feel free to change any of the wcet and periods to make it better for |
different CPU's. The mean and max execution time of each task can be seen in |
the JET display of the program. These numbers were tested on a P3 866 MHz |
machine. |
- The system will not overload with 145 hard balls, which reaches the |
maximum number of processes that shark is able to handle. In order to test |
overload, the periods of balls, or the radius of the balls could be increased |
to increase their utilization. |
- The ball and paddle tasks were given the same periods because to ensure that |
our speeds were constant across both tasks and to avoid discrepencies between |
the positions of the objects. The ai task was also given a period of 40 ms |
because it is pointless for it to update the target position of paddle2 more |
than once during a paddle2 cycle. |
- Decreasing the periods of the paddles would make the movement of the user |
paddle more responsive, if desired, because updates are only drawn to the |
screen currently every 40 ms. |
PADDLE 2 CONTROL: |
- We used the proportional and derivative control model, so the force applied |
to the paddle at a given point is: |
F = kp(distance to target position) - kd(velocity) |
Force is divided by mass to give the paddle acceleration. |
- The default values shown give some oscillation around the target position. |
Increasing kd will decrease the oscillations. Increasing both will make the |
computer harder. |
- Kp and Kd are limited to values >= 0, mass is limited to values > 0. |
SYNCHRONIZATION: |
- One mutex was used around all calls to the grx functions that write to the |
screen. |
- Another mutex was used for all accesses to the linked list of ball positions |
that was used for the p2ai task to determine which ball will hit next. |
- Both mutexes use priority inheritance to minimize blocking time of higher |
priority tasks. |
POSSIBLE NEXT STEPS: |
- Balls currently bounce from their current position once they determine that |
their next position will be out of bounds. This could be changed so that the |
balls determine the distance to the wall, subtract that distance from their |
speed, reflect the path around the wall, and end up at the new position. |
- Updating of positions for the balls and the paddles is done based cycles |
(once per cycle, the ball moves BALL_SPEED pixels). In a large time |
interval, the average speed is equal to this, but the speed in a small |
period of a ball might be greater or smaller than BALL_SPEED. This could be |
changed so that the exact time is used and during each cycle, the ball might |
move slightly more or less than BALL_SPEED pixels. In the current demo, the |
updates happen to fast for the user to notice the difference. |
- If balls move too fast, they may skip over a paddle and score a point even though the |
paddle is in the way, but at this point, the balls are too fast for the user |
to respond to them, so the game is not playable. |
- Main does keyboard reading in the current program. This could be changed to |
using keyboard hooks and having a seperate function for each key. I tried |
this implementation, but the numeric keys did not function properly, so I |
restored all key reading to main. I do not know if there would be a |
performance increase by changing them, but the switch statement would be |
removed, which would make it at least slightly more responsive. |
/unsupported/trunk/uiuc/pong/makefile |
---|
0,0 → 1,12 |
ifndef BASE |
BASE=../.. |
endif |
include $(BASE)/config/config.mk |
PROGS = pong |
include $(BASE)/config/example.mk |
pong: |
make -f $(SUBMAKE) APP=pong INIT= OTHEROBJS="initfile.o jetctrl.o" OTHERINCL= SHARKOPT="__OLDCHAR__ __GRX__" |