Subversion Repositories shark

Rev

Blame | Last modification | View Log | RSS feed

#include <kernel/kern.h>
#include <drivers/glib.h>
#include <drivers/keyb.h>
#include <semaphore.h>
//#include <stdlib.h>
#include <math.h>
#include <modules/cabs.h>
#include <modules/hartport.h>


#define NBEAM 6
#define NBALL 6

#define XMIN     50
#define XMAX     600
#define YMIN     100
#define YMAX     450
#define CONMKS 10
#define ESC      27             /* ASCII code of ESCAPE key     */

#define MOVE 0
#define FALL 1
#define FALLSTART 2
#define SLEEP 3

#define JET_ON
#define JETCTRLGRP 5


const WORD RGB_BLACK =   rgb16(  0,  0,  0);
const WORD RGB_GRAY =    rgb16(127,127,127);
const WORD RGB_WHITE =    rgb16(255,255,255);
const WORD RGB_RED    =   rgb16(255,  0,  0);
const WORD RGB_GREEN  =   rgb16(  0,255,  0);
const WORD RGB_BLUE    =  rgb16(  0,  0,255);
const WORD RGB_YELLOW  =  rgb16(255,255,  0);
const WORD RGB_MAGENTA =  rgb16(255,  0,255);
const WORD RGB_CYAN    =  rgb16(  0,255,255);
const WORD RGB_D_RED   =  rgb16(127,  0,  0);
const WORD RGB_D_GREEN =  rgb16(  0,127,  0);
const WORD RGB_D_BLUE  =  rgb16(  0,  0,127);
const WORD RGB_D_YELLOW = rgb16(127,127,  0);
const WORD RGB_D_MAGENTA = rgb16(127,  0,127);
const WORD RGB_D_CYAN   =  rgb16(  0,127,127);


const int TIMEPERIOD_MOVEBALL           = 40000;
const int TIMEPERIOD_FALLBALL           = 80000;
const int TIMEPERIOD_MOVEBEAM           = 40000;
const int TIMEPERIOD_CALCULATE_W        = 200000;
const int TIMEPERIOD_REFRESHSCREEN      = 80000;
const int TIMEPERIOD_DRAWBARGRAPHS      = 80000;
const int TIMEPERIOD_STARTBALL          = 3770400;



const int WCET_MOVEBALL                 = 1000;
const int WCET_FALLBALL                 = 1000;
const int WCET_MOVEBEAM                 = 1000;
const int WCET_CALCULATE_W              = 1000;
const int WCET_STARTBALL                = 1000;

const float GRAVITY = 9.8;
const float PI1 = 3.14;


const float LARGE_INCREASE  = 0.04;
const float MEDIUM_INCREASE = 0.02;
const float SMALL_INCREASE  = 0.005;
const float THRESHOLD_S   = 105.0f;
const float THRESHOLD_V   = 1.0f;
const int   CONSTANT_M    = 2;
const int   CONSTANT_K    = 2;


const int INITIAL_S  = 25;
const int BALLRADIUS = 8;
const int BEAMLENGTH = 100;
const int FLOOR      = 480;
const int STARTX     = 425 + 250-100;
const int STARTY     = 25;
const int BEAMPOSITION[][2] = {
  {400 + 250-100,100},
  {325 + 250-100,250},
  {475 + 250-100,250},
  {250 + 250-100,400},
  {400 + 250-100,400},
  {550 + 250-100,400}
};

int     period = 40000;         /* task period                  */
int     wcet = 1000;            /* task wcet                    */
PID     pid;
sem_t   mx_grf;                 /* mutex semaphores */


CAB palla[NBEAM];               /* CAB identifiers for communication between the ball and the beam*/
CAB beams[NBALL];               /* CAB identifiers for communication between the ball and the beam*/


char * ballNames[] = {  "p0",
                        "p1",
                        "p2",
                        "p3",
                        "p4",
                        "p5"
};

char * beamNames[] = {  "b0",
                        "b1",
                        "b2",
                        "b3",
                        "b4",
                        "b5"
};

struct BallColor
{
  int r;
  int g;
  int b;
};


struct SharedBall {
  float v;      // velocity of the ball
  float s;
  int status;
  int beamId;
  struct BallColor color ;     //ball color
};

struct Ball
{
  float x ;      //x position of the ball
  float y ;             //x position of the ball
  int r ;               //radius of the ball
  float w;      //angular velocity of the ball
  int id;
  struct SharedBall sball;
};


struct SharedBeam {
  float theta ;
  float dtheta;
};


struct Beam
{
  int l ;
  int x ;
  int y ;
  float w ;
  int id;
  struct SharedBeam sbeam;
};



int whichBeam(float s, int id) {
  int i = 0;
  switch(id) {
  case 0:
    i =  s < 0.0? 1 : 2;
    break;
  case 1:
    i =  s < 0.0? 3: 4;
    break;
  case 2:
    i =  s < 0.0? 4: 5;
    break;
  default:
    i = -1;
  }
  return i;
}


int checkifballisonbeam(float ballx,float bally, int beamid )
{
  struct SharedBeam sbeam ;
  char* p;
  float actualslope1=0.0f;
  float actualslope2=0.0f;
  const float slopetolerance = 3 ;
 
  float beamx , beamy , beamlength,requiredslope,ballposition ;
  beamx = BEAMPOSITION[beamid][0] ;
  beamy = BEAMPOSITION[beamid][1] ;
  beamlength = BEAMLENGTH ;
 
  p = cab_getmes(beams[beamid]);
  memcpy(&sbeam,p,sizeof(struct SharedBeam));
  cab_unget(beams[beamid],p);
 
  /* I  Want theta , x , y , s of the beam currospoding ot beam id .......... */
 
  actualslope1 = ( bally - beamy + slopetolerance) / (ballx - beamx) ;
  actualslope2 = ( bally - beamy - slopetolerance) / (ballx - beamx) ;
 
  requiredslope = atan(sbeam.theta) ;
 
  if (( actualslope1 >= requiredslope && actualslope2 <= requiredslope) || (actualslope2 >= requiredslope && actualslope1 <= requiredslope ))
    {
      ballposition = sqrt( (ballx-beamx)*(ballx-beamx) + (bally-beamy)*(bally-beamy) ) ;
     
      if(abs(ballposition) < beamlength )
        {
          if(ballx < beamx)
            ballposition = -ballposition ;
         
          return (int)ballposition ;
        }
     
    }
  return 10000 ;
}

TASK startBall(void* param) {
  PORT readyballs ;
  char msg[4];
  //  char str[40];
  int id = -1;
  struct SharedBall ball;
  char * p;
 
  readyballs = port_create("readyballs",4,NBALL,MAILBOX,READ);
 
  if( readyballs < 0) {
    grx_close();
    perror("Could not create to MailBox");
    cprintf("\n Could not create to MailBox ....");
    sys_abort(1);
  }
 
  while(1) {
    if( (port_receive(readyballs,msg,NON_BLOCK)) == 1 )
      {
       
        //read the ball from the cab and change the status from SLEEP to FALLSTART
        sscanf(msg,"%d",&id);
       
        /*
        sem_wait(&mx_grf);
        grx_text(msg,10+id*5,700,rgb16(255,255,255), rgb16(0,0,0));
        sem_post(&mx_grf);
        */

       
        p = cab_getmes(palla[id]);
        memcpy(&ball,p,sizeof(struct SharedBall));
        cab_unget(palla[id], p);
        ball.status = FALLSTART;
       
        //Putting the new values of the ball back in the CAB
        p = cab_reserve(palla[id]);
        memcpy(p,&(ball),sizeof(struct SharedBall));
        cab_putmes(palla[id], p);
      }
    /*else {
        sem_wait(&mx_grf);
        grx_text("Did not receive id",10,650,rgb16(255,255,255), rgb16(0,0,0));
        sem_post(&mx_grf);
      }
    */

    task_endcycle() ;
  }
 
}

TASK drawbargraphs(void* param) {
  int i;
  char* p;
  int plot_s=0;
  struct SharedBall ball;
  int x[NBALL];
  int old_s[NBALL] = {0};
  int oldx = 10;
  char str[15];
 
  const int graphpositions[][2] = {
    {10,10 },
    {120+100,10},
    {10,120+80},
    {120+100,120+80},
    {10,230+160},
    {120+100,230+160}
  };
 
 
  for(i=0;i<NBALL;i++)
    x[i]= graphpositions[i][0];
 
 
  while(1)
    {
     
      for(i=0; i < NBALL; i++) {
        //Reading the Shared ball parameters from the CAB
        p = cab_getmes(palla[i]);
        memcpy(&ball,p,sizeof(struct SharedBall));
        cab_unget(palla[i], p);
       
        plot_s = (-2 * ball.s + (2*graphpositions[i][1] + 100)) / 2 ;
       
       
       
        //Drawing the axes
       
        //Plotting the value of s
        oldx = x[i] - 1;
        if(oldx <= graphpositions[i][0] - 1) oldx = graphpositions[i][0] + 99;
       
        sem_wait(&mx_grf);
       
       
        grx_line(graphpositions[i][0],graphpositions[i][1],graphpositions[i][0],graphpositions[i][1]+100,rgb16(255,255,255));
        grx_line(graphpositions[i][0],graphpositions[i][1] + 50,graphpositions[i][0] + 100,graphpositions[i][1]+50,rgb16(255,255,255));
       
       
        grx_plot(x[i],plot_s,rgb16(ball.color.r,ball.color.g,ball.color.b));
       
        sem_post(&mx_grf);
       
        old_s[i] = plot_s;
       
       
       
        x[i]++;
        if(x[i]==graphpositions[i][0] + 100) {
          x[i]=graphpositions[i][0];
          sem_wait(&mx_grf);
          grx_box(graphpositions[i][0]-5,graphpositions[i][1]-5,graphpositions[i][0] + 110,graphpositions[i][1] + 110,rgb16(0,0,0));
          grx_line(graphpositions[i][0],graphpositions[i][1],graphpositions[i][0],graphpositions[i][1]+100,rgb16(255,255,255));
          grx_line(graphpositions[i][0],graphpositions[i][1] + 50,graphpositions[i][0] + 100,graphpositions[i][1]+50,rgb16(255,255,255));
         
          sprintf(str,"%-4d",-1*BEAMLENGTH/2);
          grx_text(str,graphpositions[i][0] -5,graphpositions[i][1]+100,rgb16(255,255,255), rgb16(0,0,0));
          sem_post(&mx_grf);
        }
       
      }
      task_endcycle() ;
    }
}


TASK moveball( void * ballparam)
{
  struct Ball ball = (*(struct Ball*)ballparam);
  struct SharedBeam beam;
  char * p;
  char str[40]; //debugging
 
  PORT readyballs ;
  char msg[4];
  int i = 10;   //debugging
 
 
  float fallingvx ;
  float fallingvy ;
 
  fallingvx = 3.0 ;
  fallingvy = 0.0 ;
 
  const float KFALLINGGRAVITY = 0.01 ;
   
  float fallingvelocityseed = 0.1  ;
 
  while(1)
    {
     
      //If the ball's status is SLEEP it reads SharedBall from the CAB  
      if(ball.sball.status == SLEEP) {
        p = cab_getmes(palla[ball.id]);
        memcpy(&(ball.sball),p,sizeof(struct SharedBall));
        cab_unget(palla[ball.id], p);
      }
      //Read the Sharedbeam parameters from the CAB
      p = cab_getmes(beams[ball.sball.beamId]);
      memcpy(&beam,p,sizeof(struct SharedBeam));
      cab_unget(beams[ball.sball.beamId], p);
     
     
      //Painting the previous position of the ball BLACK
      sem_wait(&mx_grf);
      grx_disc(ball.x, ball.y, ball.r,rgb16(0,0,0));
      sem_post(&mx_grf);
     
     
      /************************************************************************************/
      /*         THIS IS WHERE THE NEW CO-ORDINATES OF THE BALL ARE CALCULATED            */
      /************************************************************************************/
     
      if(ball.sball.status == MOVE)
        {
          ball.sball.v = ball.sball.v - CONSTANT_K * sin(beam.dtheta);
          ball.sball.s = ball.sball.s + CONSTANT_M * ball.sball.v ;
         
          ball.x = BEAMPOSITION[ball.sball.beamId][0] + ball.sball.s * cos(beam.theta);
          ball.y = BEAMPOSITION[ball.sball.beamId][1]  - ball.sball.s * sin(beam.theta) - ball.r * cos(beam.theta);
          if(abs(ball.sball.s) > BEAMLENGTH / 2)
            {
              /* Indicates that ball is not on any of the beam ....... Now Calculate will access this function to identify the balls on the beam and according to calculate the Omega .... There may be case when there are two balls on the same beam .... at that time Calculate will give priority to any of the ball...
               */

              ball.sball.beamId = whichBeam(ball.sball.s , ball.sball.beamId);
             
              fallingvx = ball.sball.v * cos(beam.theta+6.28) ;
              fallingvy = ( -1 * ball.sball.v * sin(beam.theta)) ;
             
              /*
              sem_wait(&mx_grf);
              sprintf(str,"%f %f %f",ball.sball.v,beam.theta,fallingvx);
              grx_text(str,200,700 + ball.id*10,rgb16(255,255,255), rgb16(0,0,0));
              sem_post(&mx_grf);
              */

             
             
              ball.sball.status = FALL;
                }
        }
     
     
     
      /********************************************************************************************/
      //          This status is necessary when ball is falling from the initial position ......
      /*******************************************************************************************/
     
      if(ball.sball.status == FALLSTART)
        {
          ball.sball.beamId = 0;
          ball.x = STARTX ;
          ball.y = STARTY ;
          fallingvx = fallingvelocityseed ;
          fallingvy = 0 ;
          fallingvelocityseed = - fallingvelocityseed ;
          ball.sball.status = FALL ;
        }
     
      if (ball.sball.status == FALL)
        {        
          ball.x = ball.x +  fallingvx;
          ball.y = ball.y +  fallingvy;
         
          // Change the velocity in Y direction ............
         
          fallingvy = fallingvy + GRAVITY * KFALLINGGRAVITY ;
         
          // Check the ball is reached on the floor .........
         
          if(ball.y > FLOOR)
            {
       
              readyballs = port_connect("readyballs",4,MAILBOX,WRITE);
              if(readyballs == -1) {
                grx_close();
                perror("Could not connect to MailBox");
                cprintf("\n Could not connect to MailBox ....");
                sys_abort(1);
                   }
              sprintf(msg,"%d",ball.id);
              if(port_send(readyballs,msg,NON_BLOCK)) {
                ball.sball.status = SLEEP ;
                ball.x = STARTX ;
                ball.y = STARTY ;
                p = cab_reserve(palla[ball.id]);
                memcpy(p,&(ball.sball),sizeof(struct SharedBall));
                cab_putmes(palla[ball.id], p);
              }
              /*
              else {
                sem_wait(&mx_grf) ;
                sprintf(str,"%s %d ","Unable to add ballId to the mailbox",ball.id);
                grx_text(str ,450,50 + i,  rgb16(100,103,127), rgb16(255,255,255) );
                sem_post(&mx_grf);
                }*/

              port_disconnect(readyballs);
            }
         
          //check the position of ball and if it has reached the beam
          //1)change the value of s
          //2)change status to MOVE
         
          if(ball.sball.beamId != -1)
            {
              float ballposition ;
                        if( (ballposition = checkifballisonbeam(ball.x,ball.y,ball.sball.beamId )) != 10000 )
                          {
                            /* Update the s and beam id  of the ball   in side the CABS ......*/
                            ball.sball.s = ballposition ;
                            ball.sball.v = 0 ;
                            ball.sball.status = MOVE;  
                          }
            }
         
        }
     
      /************************************************************************************/
      /*                           END OF CALCULATIONS                                    */
      /************************************************************************************/
     
      //Putting the new values of the ball back in the CAB
      if(ball.sball.status != SLEEP) {
        p = cab_reserve(palla[ball.id]);
        memcpy(p,&(ball.sball),sizeof(struct SharedBall));
        cab_putmes(palla[ball.id], p);
      }
     
     
     
      i += 2;
      if(i==400) i = 2;
     
     
      //Repainting the ball again
      sem_wait(&mx_grf);
      grx_disc(ball.x, ball.y, ball.r,  rgb16(ball.sball.color.r,ball.sball.color.g,ball.sball.color.b));
      //        sprintf(str,"%d",ball.sball.beamId);
      //        grx_text(str ,ball.x,ball.y,rgb16(100,103,127), rgb16(255,255,255) );
      sem_post(&mx_grf);
     
     
      task_endcycle();
     
    }//End of while
}

TASK calculate(void * param) { //To calculate the theta values of each beam
  int beams_covered[NBEAM] = {0};
  int i =0;
  struct SharedBall ball;
  struct SharedBeam beam;
  char *p;
  const float MAX_THETA = 0.5 ;
  const float MIN_THETA = -0.5;
 
 
 
  while(1) {
    for(i =0; i < NBEAM; i++)
      beams_covered[i] = 0;
    for(i=0; i < NBALL; i++) {
      //Reading the Shared ball parameters from the CAB
      p = cab_getmes(palla[i]);
      memcpy(&ball,p,sizeof(struct SharedBall));
      cab_unget(palla[i], p);
     
      //skip the beam theta calculation if
      //1)beam's theta was calculated earlier in the loop
      //2)If the status of the ball is falling
      if(beams_covered[ball.beamId] == 1 || ball.beamId ==-1 || ball.status == FALL || ball.status == FALLSTART || ball.status == SLEEP) continue;
     
      //read the Shared beam parameters from ball's beamId
      p = cab_getmes(beams[ball.beamId]);
      memcpy(&beam,p,sizeof(struct SharedBeam));
      cab_unget(beams[ball.beamId], p);
     
     
      /************************************************************************************/
      /*         THIS IS WHERE THE NEW theta  OF THE BEAM IS CALCULATED                   */
      /************************************************************************************/
      beam.dtheta = beam.theta;
     
      if(ball.v > 0) { //ball going towards right
        if(ball.s > 0) { //ball going away from the center
          if(abs(ball.s) < THRESHOLD_S && abs(ball.v) < THRESHOLD_V)
            {
              beam.theta = beam.theta + SMALL_INCREASE;
            } else if(abs(ball.s) > THRESHOLD_S && abs(ball.v) > THRESHOLD_V)
              {
                beam.theta = beam.theta + LARGE_INCREASE;
              } else
                {
                  beam.theta = beam.theta + MEDIUM_INCREASE;
                }
        } else {     //ball going towards center
          if(abs(ball.s) < THRESHOLD_S && abs(ball.v) < THRESHOLD_V )
            {
              beam.theta = beam.theta - SMALL_INCREASE;
            }  else
              {
                beam.theta = beam.theta - MEDIUM_INCREASE;
              }
        }
      } else {    //ball going towards left
        if(ball.s > 0) { //ball going away from the center
          if(abs(ball.s) < THRESHOLD_S && abs(ball.v) < THRESHOLD_V )
            {
              beam.theta = beam.theta + SMALL_INCREASE;
            }  else
              {
                beam.theta = beam.theta + MEDIUM_INCREASE;
              }
        } else {
          if(abs(ball.s) < THRESHOLD_S && abs(ball.v) < THRESHOLD_V )
            {
              beam.theta = beam.theta - SMALL_INCREASE;
            } else if(abs(ball.s) > THRESHOLD_S && abs(ball.v) > THRESHOLD_V)
              {
                beam.theta = beam.theta - LARGE_INCREASE;
              } else
                {
                  beam.theta = beam.theta - MEDIUM_INCREASE;
                }
        }
      }
      if(beam.theta > MAX_THETA) beam.theta = MAX_THETA;
      if(beam.theta < MIN_THETA) beam.theta = MIN_THETA;
     
     
      beam.dtheta = beam.theta - beam.dtheta;
     
      /************************************************************************************/
      /*                           END OF CALCULATIONS                                    */
      /************************************************************************************/
     
      //mark the beam as already covered
      beams_covered[ball.beamId] = 1;
     
      //write the updated SharedBeam back to the CAB
      p = cab_reserve(beams[ball.beamId]);
      memcpy(p,&beam,sizeof(struct SharedBeam));
      cab_putmes(beams[ball.beamId], p);
    }//end of for loop
   
    task_endcycle();
  }//end of task while
}

TASK movebeam( void * beamparam) {
  struct Beam beam = (*(struct Beam*)beamparam);
   
  while(1)
    {
     
      //The beam attributes(theta and dtheta) are read from the CAB.
      char *p = cab_getmes(beams[beam.id]);
      memcpy(&(beam.sbeam),p,sizeof(struct SharedBeam));
      cab_unget(beams[beam.id], p);
     
     
      //Old Parameters of the beam based on the value of theta read.
      int old_beam_start_x = beam.x - (beam.l)/2 * cos(beam.sbeam.theta - beam.sbeam.dtheta);
      int old_beam_start_y = beam.y + (beam.l)/2 * sin(beam.sbeam.theta - beam.sbeam.dtheta);
      int old_beam_end_x   = beam.x + (beam.l)/2 * cos(beam.sbeam.theta - beam.sbeam.dtheta);
      int old_beam_end_y   = beam.y - (beam.l)/2 * sin(beam.sbeam.theta - beam.sbeam.dtheta);
     
      //Painting the old beam position BLACK
      sem_wait(&mx_grf);
      grx_line(old_beam_start_x,old_beam_start_y,old_beam_end_x,old_beam_end_y,rgb16(0,0,0));
      sem_post(&mx_grf);
     
     
      //New Parameters of the beam based on the value of theta read.
      int new_beam_start_x = beam.x - (beam.l)/2 * cos(beam.sbeam.theta);
      int new_beam_start_y = beam.y + (beam.l)/2 * sin(beam.sbeam.theta);
      int new_beam_end_x   = beam.x + (beam.l)/2 * cos(beam.sbeam.theta);
      int new_beam_end_y   = beam.y - (beam.l)/2 * sin(beam.sbeam.theta);
     
      //Painting the beam again with updated values
      sem_wait(&mx_grf);
      grx_line(new_beam_start_x,new_beam_start_y,new_beam_end_x,new_beam_end_y,rgb16(255,255,255));
      sem_post(&mx_grf);
     
      //Printing some values to get current state
      sem_wait(&mx_grf) ;
      //        sprintf(str,"%d %d %s",beam.x,beam.y,"moveBeam after");
      //        grx_text(str ,485,104 + 30, RGB_GREEN, RGB_BLACK );
      sem_post(&mx_grf);
     
      task_endcycle() ;
    }
}



void byebye(void *arg)
{
  grx_close();
  cprintf("Bye Bye!\n");
}


void endfun(KEY_EVT *k)
{
  grx_close();
  cprintf("Ending...\n");
  sys_end();
}




/****************************** MAIN ******************************/

int main(int argc, char **argv)
{
  KEY_EVT k;
  SOFT_TASK_MODEL sm;
  char *p;
  char c;
  WORD r,g,b;//Colours
 
  struct Ball ballArray[NBALL];
  struct Beam beamArray[NBALL];
 
  PID balltasks[NBALL];
  PID beamtasks[NBEAM];
  PID calculate_id;
  PID drawbargraphs_id;
  PID startball_id;
   
 
  int  i = 0;         /* number of tasks created      */
 
  sem_init(&mx_grf,0,1) ;
 
  /* Set the closing function */
  sys_atrunlevel(byebye, NULL, RUNLEVEL_BEFORE_EXIT);
 
  /* graphic card Initialization */
  if (grx_init() < 1)
    {
      sys_abort(1);
    }
 
  if (grx_open(1024,768, 8) < 0)
    {
      cprintf("GRX Err\n");
      sys_abort(1);
    }
 
 
  //grx_rect(BEAMPOSITION[3][0] - 70,BEAMPOSITION[0][1] - 98,BEAMPOSITION[5][0] + 70, 510,rgb16(155,155,215));
 
  grx_line(1,600,1024,600,rgb16(155,155,215));
 
 
  //grx_line(370,1,370,600,rgb16(155,155,215));
 
  grx_text("SPACE TO CREATE NEW BALL",495, 650, rgb16(255,255,255), RGB_BLACK);
  grx_text("ENTER/ESC FOR EXIT      ",495, 665, rgb16(255,255,255), RGB_BLACK);
 
  grx_text("X: time",165, 540, rgb16(255,255,255), RGB_BLACK);
  grx_text("Y: displacement",165, 555, rgb16(255,255,255), RGB_BLACK);
 
 
  keyb_set_map(itaMap);
  k.flag = CNTR_BIT;
  k.scan = KEY_C;
  k.ascii = 'c';
  keyb_hook(k,endfun);
  k.flag = CNTL_BIT;
  k.scan = KEY_C;
  k.ascii = 'c';
  keyb_hook(k,endfun);
 
  k.flag = 0;
  k.scan = KEY_ENT;
  k.ascii = 13;
  keyb_hook(k,endfun);
 
 
  //creating cabs for shared Ball parameters
 
  for(i=0; i<NBALL; i++) {
    palla[i] = cab_create(ballNames[i], sizeof(struct SharedBall), 5);
  }
 
  for(i=0; i<NBALL; i++) {
    r=100+i*8;
    g=55+i*6;
    b=i*20;
    ballArray[i].id = i;
    ballArray[i].x = STARTX;
    ballArray[i].y = STARTY;
    ballArray[i].r = BALLRADIUS;
    ballArray[i].sball.color.r = r;
    ballArray[i].sball.color.g = g;
    ballArray[i].sball.color.b = b;
    ballArray[i].w = 0;
    ballArray[i].sball.v = 0;
    ballArray[i].sball.s = INITIAL_S + i*2;
    ballArray[i].sball.status = FALLSTART; //SLEEP;
    ballArray[i].sball.beamId = 0;
  }
 
  //put initial Sharedball structures in the CAB
  for(i=0; i<NBALL; i++) {
    p = cab_reserve(palla[i]);
    memcpy(p,&ballArray[i].sball,sizeof(struct SharedBall));
    cab_putmes(palla[i], p);
  }
 
 
 
  //creating cabs for shared Beam parameters
  for(i=0; i<NBEAM; i++) {
    beams[i] = cab_create(beamNames[i], sizeof(struct SharedBeam), 5);
  }
 
 
  for(i=0; i<NBEAM; i++) {
    beamArray[i].id = i;
    beamArray[i].x = BEAMPOSITION[i][0];
    beamArray[i].y = BEAMPOSITION[i][1];
    beamArray[i].l = BEAMLENGTH;
    beamArray[i].w = 0;
    beamArray[i].sbeam.theta = 0;
    beamArray[i].sbeam.dtheta = 0;
  }
 
  //put initial Sharedbeam structures in the CAB
  for(i=0; i<NBEAM; i++) {
    p = cab_reserve(beams[i]);
    memcpy(p,&(beamArray[i].sbeam),sizeof(struct SharedBeam));
    cab_putmes(beams[i], p);
  }
 
 
 
 
  //Creating ball tasks
  soft_task_default_model(sm);
  soft_task_def_met(sm,100);
  soft_task_def_ctrl_jet(sm);
 
  for(i=0; i <NBALL; i++) {
    soft_task_def_arg(sm,(void *)&ballArray[i]);
    soft_task_def_period(sm,TIMEPERIOD_MOVEBALL);
    balltasks[i] = task_create("Ball", moveball, &sm, NULL);
    if (balltasks[i] == NIL) {
      grx_close();
      perror("Could not create task <moveball>");
      sys_abort(1);
    }
  }
 
 
  //creating beam tasks
 
  soft_task_default_model(sm);
  soft_task_def_met(sm,100);
  soft_task_def_ctrl_jet(sm);
 
  for(i=0; i <NBEAM; i++) {
    soft_task_def_arg(sm,(void *)&beamArray[i]);
    soft_task_def_period(sm,TIMEPERIOD_MOVEBEAM);
    beamtasks[i] = task_create("Beam", movebeam, &sm, NULL);
    if (beamtasks[i] == NIL) {
      grx_close();
      perror("Could not create task <movebeam>");
      sys_abort(1);
    }
  }
 
 
 
  soft_task_default_model(sm);
  soft_task_def_met(sm,100);
  soft_task_def_ctrl_jet(sm);
  i =0;
  soft_task_def_arg(sm,(void *)i);
  soft_task_def_period(sm,TIMEPERIOD_CALCULATE_W);
  calculate_id = task_create("Calculate",calculate , &sm, NULL);
 
  if (calculate_id == NIL) {
    grx_close();
    perror("Could not create task <calculate>");
    sys_abort(1);
  }
 
 
  soft_task_default_model(sm);
  soft_task_def_met(sm,100);
  soft_task_def_ctrl_jet(sm);
  i = 0;
  soft_task_def_arg(sm,(void *)i);
  soft_task_def_period(sm,TIMEPERIOD_DRAWBARGRAPHS);
  drawbargraphs_id = task_create("DrawBarGrapphs",drawbargraphs , &sm, NULL);
 
  if (drawbargraphs_id == NIL) {
    grx_close();
    perror("Could not create task <drawbargraphs>");
    sys_abort(1);
  }
 
  //creating task <startball>
  soft_task_default_model(sm);
  soft_task_def_met(sm,100);
  soft_task_def_ctrl_jet(sm);
  i =0;
  soft_task_def_arg(sm,(void *)i);
  soft_task_def_period(sm,TIMEPERIOD_STARTBALL);
  startball_id = task_create("StartBall",startBall, &sm, NULL);
 
  if (startball_id == NIL) {
    grx_close();
    perror("Could not create task <StartBall>");
    sys_abort(1);
  }
 
 
 
  for(i=0; i<NBEAM; i++) {
    task_activate(beamtasks[i]);
  }
 
 
  task_activate(calculate_id);
 
  task_activate(drawbargraphs_id);
 
  task_activate(startball_id);
 
  i =0;
 
 
  c = keyb_getch(BLOCK);
 
 
#ifdef JET_ON
  scenario_jetcontrol();
#endif
 
#ifdef JET_ON
  init_jetcontrol();
#endif
 
  group_activate(JETCTRLGRP);
 
  do {
    if ((c == ' ') && (i < NBALL)) {
      task_activate(balltasks[i]);
      i++;
    }
    c = keyb_getch(BLOCK);
   
  } while (c != ESC);

 
 
  sys_end();
  return 0;
}

/*--------------------------------------------------------------*/