Subversion Repositories shark

Compare Revisions

Regard whitespace Rev 1664 → Rev 1665

/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__"