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 */
|
|
|
|
}
|
|
|
|
|
|
|