CSE306 Processing Systems and Structures Lockwood, Spring 2003

Machine Problem 4/5: Lunar Lander

Assigned Monday March 24, 2003
Due Date Thursday April 3, 2003, 5pm (50% of assignment) and
Thursday April 10, 2003, 5pm (remaining points)
Purpose: Interrupts & Real-time systems
Points50+50=100

Introduction

Mankind first visited the moon in 1969. The lunar lander was the vehicle that travelled from orbit to the surface of the moon.

A lunar lander is controlled by rocket engines. Rocket engines produce a constant force in the opposite direction that they are fired. The main truster points in the downward direction and is used to counteract the force of gravity. Side thusters control movement in the horizontal direction.

The goal of this machine problem is gently land your craft on the surface of the moon. Your lander will be damaged or destroyed if you descend too fast. The craft will also be destroyed if you attemped to land on a surface other than the landing pad. You will find yourself lost in space if you stray too far away from the destination. Finally, you will lose control of the thrusters if you run out of fuel.

For more information about the real lunar landings, see the references below:


Implementation

A screen dump of the working library-based version of the program that you are to write is shown below. The gauges on the left show altitude, velocities, position, and fuel. The window on the right shows the position of the craft as it approaches the surface of the moon. The small landing pad appears at the lower-left corner of the main of the window. The screen is drawn using extended ASCII characters on a text-mode video screen.

Interrupts are used to read the keyboard and perform real-time calculations at periodic intervals. The left, right, and downward arrow keys are used to control the operations of the thrusters. By reading scan codes directly from the keyboard, the program is able to decode simultaneous keypresses. A Thurster operates at full capacity while the button is pressed.

The timer is used to periodically compute new values of acceleration, velocity, and position. The function which performs these calculations is chained onto the default system timer interrupt vector and called 18 times a second.

Physical Equations

The program tracks the acceleration, velocity, and position of the lunar lander along both the horizontal and vertical directions. The lunar lander has a mass of 1000kg. The main thruster (T) provides a force of 5000 Newtons. Firing the main thruster results in an acceleration of 5 m/s^2 in the upward direction. The left and right side-thrusters (TL and TR) can each produce a force of 2000 Newtons. At all times, the lunar gravitational field accelerates the lander downward at a rate of 3 meters per second squared (m/s^2). The net motion of the lander can be determined by summing the forces.

Recall that acceleration (A) is the time derivative of velocity (V). Velocity (V) is the time derivative of position (X). For this problem, it is convienient to calculate the piece-wise integral of acceleration to obtain velocity and the piece-wise integral of velocity to calculate the position. Using Vi-1 as the previous velocity and Xi-1 as the previous postion, new values of A, V, and X can be calculated at each instant of time as shown below:

Ai = Sum of forces / Mass
Vi = Vi-1 + Ai * dt
X i= Xi-1 + Vi * dt

Numeric Representation

By carefully choosing units for time and position, integer arithmetic can be used to internally calculate acceleration, velocity, and position. Because the default PC timer interval is 1/18 second, it is convienient to measure time (dt) in units of 1/18 sec. To express acceleration in standard units of m/s^2, distance is measured in units of 1/18^2=1/324 of a meter. Using these conventions, therefore, velocity is measured in units of 1/18 m/s.

Data Display

Gauges and graphics are used to display information to the user. Division is used to display position and velocity in standard units of m and m/s. For the diagram of the lunar lander on the low-resolution text-mode screen, each horizontal column represents 2 meters and each vertical position represents 4 meters.

Procedures

You begin this problem with a set of working, modular procedures that together implement the function of the program. You will earn points by writing your own code to implement these procedures. You are strongly encouraged to experiment with the library-based mp4.exe to better understand how the program operates.

Points

You earn points by replacing each subroutine with your own code. Your score will be proportional to the percentage of the code that your write yourself. The breakdown in points is given below. Your routine MUST perform all functions of the subroutine to receive credit. If the same code is submitted by multiple authors, each author will receive 1/n points, where n is equal to the number of MPs with the same algorithms.

You are urged to test each routine as you write it. It is nearly impossible to debug a program if there are errors in the routines that it calls. Note that library routines always call other library routines. You need to call your routines directly to verify their functionality.


Preliminary Procedure

Clearifications and Erratica


MP4.ASM

PAGE 75, 132 TITLE CSE306_Lunar_Lander - Your Name - Date ; LUNAR LANDER ; ------------------- ; CSE306: Machine Problem 4/5 ; Prof. John W. Lockwood ; Washington University in Saint Louis ; March 2003 ; Online: http://www.arl.wustl.edu/~lockwood/class/cse306/mp/mp4/mp4.html ; Revision 2.1 ;====== Constants ========================================================= VIDTXTSEG EQU 0B800h ; VGA Video Segment Adddress (Text Mode) ;====== Externals ========================================================= ; -- LIB306 Routines (Free) --- extrn dspmsg:near, binasc:near, kbdin:near ; Same as MP2 and earlier ; -- LIBMP4 Routines (You need to write these) extern LibInstTime:near extern LibMyTimeInt:far extern LibDeInstallTime:near extern LibInstKey:near extern LibMyKeyInt:far extern LibDeInstallKey:near extern LibDrawScreen:near extern LibReDrawScreen:near extern LibFinalScreen:near extern mp4xit:near public InstTime, MyTimeInt, DeInstallTime, InstKey, MyKeyInt public DeInstallKey, DrawScreen, ReDrawScreen, FinalScreen ;====== Stack ============================================================ stkseg segment stack db 64 dup ('STACK ') stkseg ends ;====== Begin Code/Data segment ========================================== cseg segment public 'CODE' assume cs:cseg, ds:cseg, ss:stkseg, es:nothing ;====== Variables ======================================================== a_x dw 0 ; Horizontal Acceleration (m/s^2) v_x dw 18 ; Horizontal Velocity (1/18 m/s) x dw 0 ; Horizontal Position (1/324 m) a_y dw 0 ; Vertical Acceleration (m/s^s) v_y dw 0 ; Vertical Velocity (1/18 m/s) y dw 60*324 ; Vertical Position (1/324 m) G dw 3 ; Gravity (m/s^2) T dw 0 ; Main Thruster (m/s^2) TL dw 0 ; Left Thruster (m/s^2) TR dw 0 ; Right Thruster (m/s^2) Time dw 0 ; Flight Time (1/18 sec) Fuel_Init dw 2000 ; Initial Amount of Fuel (Full Tank) fuel dw ? ExitFlag db 0 ; 0=Run, 1=Exit - Set by keyboard Interrupt handler OldTimeVector dd ? ; Segment:Offset of Original Interrupt Vector OldKeyVector dd ? ; Segment:Offset of Original Keyboard Vector ;====== PUBLICs (variables available to LibMP4) =========================== PUBLIC x,v_x,a_x,y,v_y,a_y,G,T,TL,TR ; Variables available to LIBMP4 PUBLIC Time,Fuel_Init,fuel,ExitFLag PUBLIC OldTimeVector, OldKeyVector ;====== Procedures ======================================================= ; -------------------------------------- ; Your subroutines go here ; -------------------------------------- InstTime proc near Call LibInstTime ; Comment out this line to use your own code ret InstTime endp MyTimeInt proc far ; This is an Interrupt Service Routine ; Save ALL registers that you modify ; You cannot DS is set when called, but can set it to CS PUSHF ; Comment out these TWO lines Call cs:LibMyTimeInt ; to use your own code! iret ; Return from Interrupt MyTimeInt endp DeInstallTime proc near Call LibDeInstallTime ; Comment out this line to use your own code ret DeInstallTime endp InstKey proc near Call LibInstKey ; Comment out this line to use your own code ret InstKey endp MyKeyInt proc far ; This is an Interrupt Service Routine ; Save ALL registers that you modify ; You cannot DS is set when called, but can set it to CS PUSHF ; Comment out these TWO lines Call cs:LibMyKeyInt ; to use your own code! iret ; Return from Interrupt MyKeyInt endp DeInstallKey proc near Call LibDeInstallKey ; Comment out this line to use your own code ret DeInstallKey endp DrawScreen proc near Call LibDrawScreen ; Comment out this line to use your own code ret DrawScreen endp ReDrawScreen proc near Call LibReDrawScreen ; Comment out this line to use your own code ret ReDrawScreen endp FinalScreen proc near Call LibFinalScreen ; Comment out this line to use your own code ret FinalScreen endp ;====== SECTION 6: Main procedure ========================================= main proc far mov ax, cseg ; Initialize DS=CS mov ds, ax mov ax,0B800h ; Load ES with video Segment mov es,ax mov AX,2 ; Set Video Card to operate in 80x25 Text Mode int 10h MOV AX,Fuel_Init ; Fill the Fuel tank with a full tank MOV Fuel,AX call drawscreen ; Draw the Initial Screen call InstTime ; Install Timer Interrupt Service Routine call InstKey ; Install Keyboard Interrupt Service Routine showc: call RedrawScreen ; Main body of the program CMP ExitFlag,0 ; Repeat until ExitFlag is set by key press JE showc call ReDrawScreen ; Final Refresh call FinalScreen ; Draw Final Score Call DeInstallKey ; Restore original INT9 Call DeInstallTime ; Restore original INT8 Call mp4xit ; Exit the program main endp cseg ends end main