JSR GetMoments \ Set the following: \ \ xTemp3 = yLiftDrag - (xTurn * 250 / 256) \ = yVelocityP * 2 - (xTurn * 250 / 256) \ \ yTemp3 = xLiftDrag - (yTurn * 250 / 256) \ = xVelocityP * 2 - (yTurn * 250 / 256) \ \ zTemp3 = -zTurn * 2 \ A reminder that we set the following in part 1: \ \ (SS RR) = max(|velocityP|) * 2 * ~yPlaneHi / 256 LDA RR \ Set (S R) = (SS RR) with bit 0 of the low byte cleared AND #%11111110 \ to convert this into a value with the sign in bit 0 STA R \ and the value as follows (we drop the "* 2" as bit 0 LDA SS \ is now the sign bit): STA S \ \ (S R) = max(|velocityP|) * ~yPlaneHi / 256 LDX #5 \ Set X as a loop counter from 5 down to 0 LDA #0 \ Change the rounding in Multiply16x16Mix so that it STA mult1+1 \ rounds down, i.e. uses floor to round .aero12 CPX #3 \ If X >= 3, jump to aero13 to skip the following BCS aero13 \ For X = 0 to 2, we now fetch the relevant axis of \ xTemp3, which we set above to: \ \ xTemp3 = yVelocityP * 2 - (xTurn * 250 / 256) \ \ yTemp3 = xVelocityP * 2 - (yTurn * 250 / 256) \ \ zTemp3 = -zTurn * 2 LDY xTemp3Lo,X \ Set (A Y) = xTemp3 (or yTemp3 or zTemp3) LDA xTemp3Hi,X JMP aero14 \ Jump to aero14 .aero13 \ For X = 3 to 5, we now fetch the relevant axis of \ xLiftDrag, which we set in part 1 to: \ \ xLiftDrag = xVelocityP * 2 \ \ yLiftDrag = yVelocityP * 2 \ \ zLiftDrag = zVelocityP * 2 LDY xMomentsLo,X \ Set (A Y) = xLiftDrag (or yLiftDrag or zLiftDrag) LDA xMomentsHi,X .aero14 STA J \ Set (J I) = (A Y) STY I \ \ = xTemp3 for X = 0 to 2 \ \ xVelocityP * 2 for X = 3 to 5 LDA #0 \ Set K = 0, so Multiply16x16Mix doesn't negate the STA K \ result, and returns the sign of the result in K STX VV \ Store the loop counter in VV, so we can retrieve it \ below JSR Multiply16x16Mix \ Call Multiply16x16Mix to calculate: \ \ (H G W) = (J I) * (S R) / 256 \ \ = xTemp3 * max(|velocityP|) * ~yPlaneHi \ \ xVelocityP * 2 * max(|velocityP|) * ~yPlaneHi LDA K \ If the result of the multiplication is positive, jump BPL aero15 \ to aero15 to skip the following SEC \ The result of the multiplication is negative, so now LDA #0 \ we negate (H G W), starting with the low bytes SBC W STA W LDA G \ Then the middle bytes SBC #0 STA G BCS aero15 \ And finally the high bytes DEC H .aero15 LDX VV \ Retrieve the value of the loop counter X that we \ stored in VV above LDY #0 \ Set Y = 0 to act as a shift counter in the loop below, \ so by default it shifts the result left by 1 place LDA G \ Set (H A W) = (H G W) CPX #3 \ If X < 3, jump to aero16 BCC aero16 CPX #5 \ If X = 5, jump to aero16 BEQ aero16 INY \ If we get here then X = 3 or 4, so increment Y to 2 so INY \ the following loop shifts (H A W) left by 3 places \ We now shift (H A W) left by Y + 1 places .aero16 ASL W \ Set (H A W) = (H A W) << 1 ROL A ROL H DEY \ Decrement the shift counter BPL aero16 \ Loop back until we have shifted left by Y + 1 places, \ so that's the same as: \ \ (H A W) = (H A W) * 8 if X = 3 or 4 \ \ (H A W) = (H A W) * 2 otherwise STA xMomentsLo,X \ Set xMoments or xLiftDrag = (H A) LDA H STA xMomentsHi,X DEX \ Decrement the loop counter to move onto the next BPL aero12 \ Loop back until we have set xMoments to zMoments and \ xLiftDrag to zLiftDrag, so we now have: \ \ xMoments = xTemp3 * maxv * ~yPlaneHi * 2 \ = (yVelocityP * 2 - (xTurn * 250 / 256)) \ * maxv * ~yPlaneHi * 2 \ \ yMoments = yTemp3 * maxv * ~yPlaneHi * 2 \ = (xVelocityP * 2 - (yTurn * 250 / 256)) \ * maxv * ~yPlaneHi * 2 \ \ zMoments = zTemp3 * maxv * ~yPlaneHi * 2 \ = -zTurn * 2 * maxv * ~yPlaneHi * 2 \ \ xLiftDrag = xVelocityP * 2 * maxv * ~yPlaneHi * 8 \ \ yLiftDrag = yVelocityP * 2 * maxv * ~yPlaneHi * 8 \ \ zLiftDrag = zVelocityP * 2 * maxv * ~yPlaneHi * 2 \ \ where: \ \ maxv = max(|xVelocityP|, |yVelocityP|, |zVelocityP|) LDA #128 \ Change the rounding in Multiply16x16Mix back to the STA mult1+1 \ default, so it rounds to the nearest integer LDA xLiftDragLo \ Set zSlipMoment = xLiftDrag STA zSlipMomentLo LDA xLiftDragHi STA zSlipMomentHi LDA zLiftDragHi \ If zLiftDrag is negative, jump to aero19 to return BMI aero19 \ from the subroutine \ If zLiftDrag is positive, then we now move on to set \ yFlapsLift and xMoments STA W \ Set the following: STA yFlapsLiftHi \ LDA #0 \ (G W A) = (0 zLiftDragHi zLiftDragLo) STA G \ = zLiftDrag LDA zLiftDragLo \ STA yFlapsLiftLo \ yFlapsLift = zLiftDrag LDX #2 \ Set X = 2 to act as a shift counter in the loop below, \ so by default it shifts the result left by 3 places LDA flapsStatus \ Set A to the current flap status (0 if flaps are off, \ 1 if they are on) PHP \ Store the flags on the stack, so we can check the flap \ status later on BEQ aero17 \ If the flaps are off, skip the following instruction LDX #1 \ Set X = 1 so the following loop shifts (G W A) left by \ 2 places \ We now shift (G W A) left by X + 1 places, so that's: \ \ (G W A) = zLiftDrag << 3 if the flaps are off \ \ (G W A) = zLiftDrag << 2 if the flaps are on .aero17 ASL A \ Set (G W A) = (G W A) << 1 ROL W ROL G DEX \ Decrement the shift counter BPL aero17 \ Loop back until we have shifted left by X + 1 places PLP \ Restore the processor flags, so this jumps to aero18 BEQ aero18 \ if flapsStatus is zero, i.e. the flaps are off SEC \ The flaps are on, so negate (G W) JSR Negate16Bit .aero18 \ We now have the following: \ \ (G W A) = zLiftDrag << 3 if the flaps are off \ \ (G W A) = -zLiftDrag << 2 if the flaps are on CLC \ Set xMoments = xMoments + (G W) LDA W \ ADC xMomentsLo \ starting with the low bytes STA xMomentsLo LDA G \ And then the high bytes ADC xMomentsHi STA xMomentsHi \ So if zLiftDrag is negative, we now have the \ following: \ \ xMoments = xMoments + zLiftDrag << 3 when the flaps \ = xMoments + (zLiftDrag * 8) are off \ \ xMoments = xMoments - zLiftDrag << 2 when the flaps \ = xMoments - (zLiftDrag * 4) are on .aero19 RTS \ Return from the subroutineName: ApplyAerodynamics (Part 3 of 3) [Show more] Type: Subroutine Category: Flight model Summary: Calculate various aerodynamic figures Deep dive: The flight modelContext: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
This part calculates the following: [ xMoments ] = [ yVelocityP * 2 - xTurn * 250 / 256 ] [ yMoments ] = [ xVelocityP * 2 - yTurn * 250 / 256 ] * maxv * airDensity [ zMoments ] = [ -zTurn * 2 ] [ xLiftDrag ] = [ xVelocityP * 2 * 4 ] [ yLiftDrag ] = [ yVelocityP * 2 * 4 ] * maxv * airDensity [ zLiftDrag ] = [ zVelocityP * 2 ] zSlipMoment = xLiftDrag where: airDensity = ~yPlaneHi * 2 maxv = max(|xVelocityP|, |yVelocityP|, |zVelocityP|) If zLiftDrag is positive we also do: yFlapsLift = zLiftDrag xMoments = xMoments + (zLiftDrag * 8) when the flaps are off xMoments - (zLiftDrag * 4) when the flaps are on
[X]
Subroutine GetMoments (category: Flight model)
Calculate the pitching, rolling and yawing moments due to the current pitch, roll and yaw rates
[X]
Subroutine Multiply16x16Mix (category: Maths)
Multiply two 16-bit numbers with different sign bits (one in bit 7 of the high byte, the other in bit 0 of the low byte)
[X]
Subroutine Negate16Bit (category: Maths)
Negate a 16-bit number
[X]
Label aero12 is local to this routine
[X]
Label aero13 is local to this routine
[X]
Label aero14 is local to this routine
[X]
Label aero15 is local to this routine
[X]
Label aero16 is local to this routine
[X]
Label aero17 is local to this routine
[X]
Label aero18 is local to this routine
[X]
Label aero19 is local to this routine
[X]
Variable flapsStatus in workspace Main variable workspace
Flaps status
[X]
Label mult1 in subroutine Multiply16x16
[X]
Variable xLiftDragHi in workspace Main variable workspace
Linear force due to lift in the x-axis (high byte)
[X]
Variable xLiftDragLo in workspace Main variable workspace
Linear force due to lift in the x-axis (low byte)
[X]
Variable xMomentsHi in workspace Main variable workspace
Angular force due to airflow over the plane in the x-axis (high byte)
[X]
Variable xMomentsLo in workspace Main variable workspace
Angular force due to airflow over the plane in the x-axis (low byte)
[X]
Variable xTemp3Hi in workspace Main variable workspace
The high byte of the xTemp3 temporary variable
[X]
Variable xTemp3Lo in workspace Main variable workspace
The low byte of the xTemp3 temporary variable
[X]
Variable yFlapsLiftHi in workspace Main variable workspace
Linear force in the y-axis due to lift from the flaps (high byte)
[X]
Variable yFlapsLiftLo in workspace Main variable workspace
Linear force in the y-axis due to lift from the flaps (low byte)
[X]
Variable zLiftDragHi in workspace Main variable workspace
Linear force due to drag in the z-axis (high byte)
[X]
Variable zLiftDragLo in workspace Main variable workspace
Linear force due to drag in the z-axis (low byte)
[X]
Variable zSlipMomentHi in workspace Main variable workspace
Angular force in the z-axis due to aircraft slip (high byte)
[X]
Variable zSlipMomentLo in workspace Main variable workspace
Angular force in the z-axis due to aircraft slip (low byte)