/*
    LKDEMORT.C

    BL11xx/Little Giant, Tiny Giant

    Demonstration of real-time kernel contained in library, works
    with KDM to change set temperature.


    Real time kernel timer scheduling calls

    request(unsigned ntask) -- request that a task be run or resumed

    run_every(unsigned ntask, unsigned nticks) -- schedule every nticks ticks

    run_after(unsigned ntask, unsigned long nticks) -- schedule after nticks
                                                        have passed

    run_at( unsigned ntask, int *timer) -- schedule at or after the 48 bit
                                            time pointed to by *timer

    suspend(unsigned nticks) -- call from a task only with nticks <= 255.
                                Blocks running until nticks passed. 
                                When nticks changes to zero, task is scheduled
                                again. Other scheduling (every, after at)
                                is updated while task is blocked and resumes
                                after suspension has timed out. If nticks
                                is zero, then task is stopped until an 
                                external force requests it starts again, 
                                either run (every, after, at) or request.

    int run_timer() -- call from timer interrupt at 10-500 times
                                per second.


*/

/***Begin Globals real_time_kernel  */

int task0(),task1(),task2(),task3(),task4(),task5(),backgnd();
int (*Ftask[])()={task0,task1,task2,task3,task4,task5,backgnd};

char comment_flag;

#define NTASKS 7

#define TASK0 0
#define TASK1 1
#define TASK2 2
#define TASK3 3
#define TASK4 4
#define TASK5 5

#define RUNKERNEL 1                 /* turn on PRT1 sharing */

#use rtk.lib

/***End Globals real_time_kernel */

#define KEYPAD_SIZE  24
#ifdef LK_COLS
#undef LK_COLS
#endif
#define LK_COLS 20

#ifdef LK_LINES
#undef LK_LINES
#endif
#define LK_LINES 4


#use kdm.lib

/**** Use these values for 4X40
//#define KEYPAD_SIZE  40
//#ifdef LK_COLS
//#undef LK_COLS
//#endif
//#define LK_COLS 40
**/

main() 
{
	_GLOBAL_INIT();
    outport (DCNTL, 0x30);                /* set I/O wait states to 4 */
    DI();
    hitwd();
    vat_init();
    hitwd();
    comment_flag=0;
    lk_init_keypad ();                    /* init keypad, lcd, and RTK */
    run_every(TASK5,20);                   /* run task 5 every 5 ticks  */
    run_every(TASK1,20);                   /* run task 1 every 5 ticks  */
    run_every(TASK4,20);                   /* run task 4 every 5 ticks  */
    EI();                                 /* let it start running      */
    backgnd();                            /* this runs after everything else */
}

goxy(int x, int y)
{
    printf("\x1b=%c%c",x+32,y+32);
}

shared float temp; /* temperature in degrees C */
shared float settemp; /* temperature setting */
shared float volume; /* amount of liquid in vat */
shared char heater; /* 1- heater on */
shared char intake; /* 1- intake valve open */
shared char level; /*  1- water level above switch */
shared int station;
shared int xtrain,ytrain;
shared int waiting;
char comment[60];

task0()
{        /* not currently used */
}

/* simulate the target system */
/* the outflow rate is 10 units / tick
   the inflow rate is 25 units / tick when intake is open 
   the temperature of the intake liquid is 20
   the settemp must be higher
   the capacity of the vessel 1000 units of liquid
   the capacity of the heater is to raise the temperature 1 degree per tick
*/

vat_init()
{
    temp=30.0; 
    volume=1000.0; 
    settemp=56.0; 
    station=0;
}

task1()
{
	hitwd();
    if (intake) 
      temp=0.985 * temp + 20.0 * 0.015; /* dilute with 15 liters at 20C */

    if (heater) 
      temp = temp + 1.0;

    if (intake) 
      volume = volume + 15.0; 
    else 
      volume = volume - 10.0;

    if (volume > 1000.0) 
      level = 0; 
    else 
      level = 1;

    request (TASK2); /* request the control loop */
}

/* regulate the temperature and level in vessel */
task2()
{
   intake = level;          /* if level low, enable intake valve */
   heater = temp < settemp; /* if temp low, turn on heater */
}

task3()
{  /* not used */

}

task4()
{
    static k;
    while (comment_flag) suspend(5);            /* if display not updated */

    strcpy (comment, "Begin at Sacramento, Ca.");
    comment_flag = 1;

    xtrain = 30; ytrain = 1;                 /* at Sacramento station */
    suspend (60);                            /* wait in Sacramento station */
    while (comment_flag) suspend(5);         /* wait for display update */
    strcpy (comment, "Leave Sacramento");
    comment_flag=1;
    
    /* Sacto to Davis */
    for (k = 31; k < 48; k++) 
    {
      xtrain = k; 
      suspend (15);
    } 
    while (comment_flag) suspend(5); 
    strcpy (comment, "Stop at Davis");
    comment_flag = 1;
    suspend (40); /* wait at Davis station */
    while (comment_flag) suspend (5); 
    strcpy (comment, "Leave Davis");
    comment_flag=1;

    for (k = 48; k < 63; k++) { xtrain=k; suspend(8); }
    while (comment_flag) suspend (5); 
    strcpy (comment, "Stop at Oakland");
    comment_flag = 1;
    suspend (60); /* wait at Oakland station */
    while (comment_flag) suspend (5); 
    strcpy (comment, "Leave Oakland");
    comment_flag = 1;

    for (k=1; k<4; k++) {ytrain = k; suspend(20);}
    while (comment_flag) suspend(5); 
    strcpy (comment, "Arrive at San Jose");
    comment_flag = 1;
    suspend (60); /* wait at San Jose Stations */
}

task5()
{
   runwatch ();
}

backgnd()
{
    int k;
    static int intakeold, heaterold,xtold,ytold;
    static float tempold,volumeold,setold;

    k=0;
    xtold=70; ytold=2;
    setold=0.;
    goxy(0,0);
    printf("Real-time kernel demo");

    goxy(0,1); printf("temp=");
    goxy(0,2); printf("volume=");
    goxy(30,0); printf("Sacramento");
    goxy(45,0); printf("Davis");
    goxy(60,0); printf("Oakland");
    goxy(60,4); printf("San Jose");
    goxy(19,4); printf("lower left keys on KDM to change");

   while (1)
   {
      if (xtold != xtrain || ytold != ytrain)
      {
         goxy (xtold,ytold); printf(" ");
         xtold = xtrain; ytold = ytrain;
         goxy (xtold,ytold); printf("T");
      }

      if(setold != settemp)    
      {
         goxy(0,4); 
         printf("set temp.=%5.2f",setold=settemp);
      }
    
      if (temp != tempold) 
      {
         goxy(8,1); 
         printf("%8.2f",temp); 
         tempold=temp;
      }
    
      if (volume != volumeold) 
      {
         goxy(8,2); 
         printf("%8.2f",volumeold=volume);
      }

      if (intake != intakeold || heaterold != heater) 
      {
         goxy(0,3); 
         printf("intake=%d  heater=%d",intake,heater);
         heaterold = heater; 
         intakeold = intake;
      }

      if(comment_flag) 
      {
         goxy(30,2); 
         printf ("                        ");
         goxy(30,2); 
         printf("%s",comment); 
         comment_flag = 0;
      }

      // check keypad
      if((k = lk_kxget (0)) >= 0)
      {
         if(k == 2) settemp = settemp + 1.0;
         if(k == 1) settemp = settemp - 1.0;
      }
   }
}