483 lines
11 KiB
Plaintext
483 lines
11 KiB
Plaintext
_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 */
|
||
|
||
}
|
||
|
||
|
||
|