_Real-Time Modleing with MS-DOS_
by David Bowling

[LISTING ONE]


 #include <dos.h>

 #define  TRUE   -1
 #define  FALSE   0

 void user_defined_background_task();
 void set_up_user_background_task();
 void set_down_user_background_task();
 void set_up_user_real_time_task();
 void set_down_user_real_time_task();
 void set_up_real_time_task();
 void set_down_real_time_task();

 int not_done = TRUE;
 int over_run = FALSE;

 main(){
   set_up_user_real_time_task();     /*initialization section*/
   set_up_real_time_task();
   set_up_user_background_task();

   while( not_done && ! over_run){    /*background task loop*/
   user_defined_background_task();
   }

   set_down_real_time_task();         /*termination section*/
   set_down_user_background_task();
   set_down_user_real_time_task();

   if( over_run )
     printf("Error exit, frame over run\n");
  }





[LISTING TWO]

 void interrupt real_time_task();
 void interrupt (*old_clock_func)();
 void set_timer();
 int user_define_divisor = 1; /*initialize in case user forgets*/

 void set_up_real_time_task()
 {
   void interrupt (*getvect())();

   old_clock_func = getvect( 0x08 );/*save original clock vector*/
    setvect( 0x50, old_clock_func );/*store in unused location*/
    setvect( 0x08, real_time_task ); /*overwrite with real-time*/
   set_timer( user_define_divisor ); /*set system timer*/
 }

 void set_down_real_time_task(){
   setvect( 0x08, old_clock_func ); /*restore clock vector*/
   set_timer( 1 );                  /*reset system timer*/
 }


[LISTING THREE]


 int running = FALSE;
 int inter_count = 0;

 void interrupt real_time_task(){
   enable();

   if( !running && !over_run ){
     running = TRUE;
     user_defined_real_time_task(); /*real-time function*/
   }else{
     over_run = TRUE;
   };

   if( inter_count == user_define_divisor ){
     geninterrupt( 0x50 );     /*call system clock*/
     inter_count = 0;
   }else{
     outport( 0x20, 0x20 );    /*8259 end of interrupt routine*/
     inter_count += 1;
   };

   running = FALSE;
 }





[LISTING FOUR]

 void set_timer( divisor )
   int divisor;
 {
   int cnt;
   int lo, hi;

   cnt = 65536 / divisor;

   lo = cnt % 256;
   hi = cnt / 256;

   outportb( 0x43, 0x36 );
   outportb( 0x40, lo );    /*write tic counter*/
   outportb( 0x40, hi );
 }


[LISTING FIVE]

 int i = 0;  /* DATAPOOL */

 user_defined_background_task(){
   printf("i = %d\n", i );
 }

 user_defined_real_time_function(){
   i += 1;
 }




[LISTING SIX]

     union{
      char coprocessor_state[94];
      int control_word;
    }float_save;

     /* save coprocessor state */
     asm   fsave float_save.coprocessor_state
     asm   fldcw float_save.control_word
              .
              .
              .
     /* restore coprocessor state */
     asm   frstor float_save.coprocessor_state



[LISTING SEVEN]


   while( not_done && ! over_run ){   /* non real-time debugging*/
     user_defined_background_task();
     user_defined_real_time_task();
   }



[LISTING EIGHT]

 #include <dos.h>

 #define  TRUE   -1
 #define  FALSE   0

 void user_defined_background_task();
 void set_up_user_background_task();
 void set_down_user_background_task();
 void set_up_user_real_time_task();
 void set_down_user_real_time_task();
 void set_up_real_time_task();
 void set_down_real_time_task();

 int not_done = TRUE;
 int over_run = FALSE;

 main(){
   set_up_user_real_time_task();     /*initialization section*/
   set_up_real_time_task();
   set_up_user_background_task();

   while( not_done && ! over_run){    /*background task loop*/
     user_defined_background_task();
   }

   set_down_real_time_task();         /*termination section*/
   set_down_user_background_task();
   set_down_user_real_time_task();

   if( over_run )
     printf("Error exit, frame over run\n");
  }

/******************************************************/

 void interrupt real_time_task();
 void interrupt (*old_clock_func)();
 void set_timer();
 int user_define_divisor = 1; /* initialize in case user forgets */

 void set_up_real_time_task()
 {
   void interrupt (*getvect())();

   old_clock_func = getvect( 0x08 ); /*save original clock vector*/
   setvect( 0x50, old_clock_func );  /*store in unused location*/
   setvect( 0x08, real_time_task );  /*overwrite with real-time*/
   set_timer( user_define_divisor ); /*set system timer*/
 }

 void set_down_real_time_task(){
   setvect( 0x08, old_clock_func ); /*restore clock vector*/
   set_timer( 1 );                  /*reset system timer*/
 }

/******************************************************/

 union{
   char coprocessor_state[94];
   int control_word;
 } float_save;

 int running = FALSE;
 int inter_count = 0;

 void interrupt real_time_task(){
   /* save coprocessor state */
   asm   fsave float_save.coprocessor_state
   asm   fldcw float_save.control_word

   enable();

   if( !running && !over_run ){
     running = TRUE;
     user_defined_real_time_task(); /*real-time function*/
   }else{
     over_run = TRUE;
   };

   if( inter_count == user_define_divisor ){
     geninterrupt( 0x50 );     /*call system clock*/
     inter_count = 0;
   }else{
     outport( 0x20, 0x20 );    /*8259 end of interrupt routine*/
     inter_count += 1;
   };

   running = FALSE;

   /* restore coprocessor state */
   asm   frstor float_save.coprocessor_state
 }

/******************************************************/

 void set_timer( divisor )
   int divisor;
 {
   int cnt;
   int lo, hi;

   cnt = 65536 / divisor;

   lo = cnt % 256;
   hi = cnt / 256;

   outportb( 0x43, 0x36 );
   outportb( 0x40, lo );    /*write tic counter*/
   outportb( 0x40, hi );
 }

/******************************************************/



[LISTING NINE]

double x;                     /* DATAPOOL */
extern int user_define_divisor;

#define  m     1.0134145    /* define spring-mass constants */
#define  k     10.0
#define  zeta  0.01
#define  x_o   30.0

#define  frame_time 0.013725

double t = 0.0;   /* real-time */
double c1;    /* real-time constants */
double c2;
double c3;
double c4;

void set_up_user_real_time_task(){
 double omega;
 double temp;
 double sqrt();

 user_define_divisor = 4;   /* set user divisor counter */

 omega = sqrt( k / m );
 temp  = sqrt( 1.0 - zeta * zeta );

 c1 = - zeta * omega;     /* compute real-time constants */
 c2 = zeta * x_o / temp;
 c3 = temp * omega;
 c4 = x_o;
}

void set_down_user_real_time_task(){   /* no set down necessary */
}

void user_defined_real_time_task(){
 double cos();
 double sin();
 double exp();
                  /* spring-mass model */
 x = exp( c1 * t ) * ( c2 * sin( c3 * t ) + c4 * cos( c3 * t ) );

 t += frame_time;
}



[LISTING TEN]

#include "graphics.h"

#define FALSE  0
#define TRUE   -1

extern int not_done;
extern double x;   /* DATAPOOL */

int x_off = 320;
int y_off = 100;

stationary[11][4] = { {   0,   0,   0,  -5 },   /* base */
                     {   0,   0,   7,   0 },
                     { -40,  -5,  40,  -5 },
                     { -35,  -5, -30, -12 },
                     { -25,  -5, -20, -12 },
                     { -15,  -5, -10, -12 },
                     {  -5,  -5,   0, -12 },
                     {   5,  -5,  10, -12 },
                     {  15,  -5,  20, -12 },
                     {  25,  -5,  30, -12 },
                     {  35,  -5,  40, -12 } };

void set_up_user_background_task(){
 int  i, j;
 int  g_driver = EGA;
 int  g_mode   = EGAHI;
 char d_path[] = {""};
 int g_error;

 if( registerbgidriver( EGAVGA_driver ) < 0 ){   /* EGA driver */
   printf("ERROR: can't register ega/vga driver\n");
   exit();
 };

 initgraph( &g_driver, &g_mode, d_path );
 g_error = graphresult();
 if( g_error < 0 ){
   printf("ERROR: %s\n", grapherrormsg(g_error) );
   exit( 0 );
 };

 setcolor( YELLOW );

 for( i = 0; i < 2; ++i ){   /* setup spring */
   setactivepage( i );
   for( j = 0; j < 11; ++j ){
     line( stationary[j][0] + x_off, stationary[j][1] + y_off,
           stationary[j][2] + x_off, stationary[j][3] + y_off);
   };
 };

}

void set_down_user_background_task()
{
 closegraph();
}

double stretch[12][4] = { {  7.0,  0.0, -7.0,  5.0 },   /* spring */
                         { -7.0,  5.0,  7.0, 10.0 },
                         {  7.0, 10.0, -7.0, 15.0 },
                         { -7.0, 15.0,  7.0, 20.0 },
                         {  7.0, 20.0, -7.0, 25.0 },
                         { -7.0, 25.0,  7.0, 30.0 },
                         {  7.0, 30.0, -7.0, 35.0 },
                         { -7.0, 35.0,  7.0, 40.0 },
                         {  7.0, 40.0, -7.0, 45.0 },
                         { -7.0, 45.0,  7.0, 50.0 },
                         {  7.0, 50.0, -7.0, 55.0 },
                         { -7.0, 55.0,  7.0, 60.0 } };
int move[ 6][4] = { { -30,  5,  30,   5 },              /* mass */
                   { -30, 40,  30,  40 },
                   { -30,  5, -30,  40 },
                   {  30,  5,  30,  40 },
                   {   0,  0,   0,   5 },
                   {   0,  0,   7,   0 } };

void user_defined_background_task(){
 double ratio;
 int x_spring;
 int i, j;
 static int start = 1;
 static int buff[2][100][4];
 static int cnt[2];
 static int b = 0;
 static int p = 0;

 if( start ){
   set_page( p );
   p = ( p )? 0: 1;
   setactivepage( p );
 };

 if( kbhit() ){
   not_done = FALSE;
 };

 x_spring = x + 30.0;
 ratio = 1.0 + ( (double)x / 60.0 );

 cnt[b]  = 0;

 setcolor( RED );                             /* draw mass */
 for( i = 0, j = cnt[b]; i < 6; ++i, ++j ){
   buff[b][j][0] = move[i][0] + x_off;
   buff[b][j][1] = move[i][1] + y_off + x_spring + 30;
   buff[b][j][2] = move[i][2] + x_off;
   buff[b][j][3] = move[i][3] + y_off + x_spring + 30;
   line( buff[b][j][0], buff[b][j][1], buff[b][j][2], buff[b][j][3] );
 };
 cnt[b] += 6;

 setcolor( GREEN );                           /* draw spring */
 for( i = 0, j = cnt[b]; i < 12; ++i, ++j ){
   buff[b][j][0] = stretch[i][0] + x_off;
   buff[b][j][1] = (int)( stretch[i][1] * ratio ) + y_off;
   buff[b][j][2] = stretch[i][2] + x_off;
   buff[b][j][3] = (int)( stretch[i][3] * ratio ) + y_off;
   line( buff[b][j][0], buff[b][j][1], buff[b][j][2], buff[b][j][3] );
 };
 cnt[b] += 12;

 b = ( b )? 0: 1;

 set_page( p );
 p = ( p )? 0: 1;
 setactivepage( p );   /* switch page */

 if( ! start ){
   setcolor( BLACK );                /* undraw picture */
   for( i = 0; i < cnt[b]; ++i )
     line( buff[b][i][0], buff[b][i][1], buff[b][i][2], buff[b][i][3] );
 }else{
   start = 0;
 };
}

set_page(n)      /* set visual page */
 int n;
{
 int far *farptr;
 int addr;

 setvisualpage( n );

 farptr = (int far *)0x00400063;     /* status register address */
 addr = *(farptr) + 6;

 while( ( inport( addr ) & 0x08 ) == 0x08 );  /* while in vert retrace */
 while( ( inport( addr ) & 0x08 ) != 0x08 );  /* while not in vert retrace */

}