Skip to navigation

Aviator on the BBC Micro

Flight model: ApplyFlightControl

Name: ApplyFlightControl [Show more] Type: Subroutine Category: Flight model Summary: Calculate the effects of the primary flight controls (elevator, rudder and ailerons), and implement the "instant centre" feature Deep dive: The flight model On-ground calculations
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * ApplyFlightModel (Part 2 of 7) calls ApplyFlightControl

This routine sets the following, depending on the current position of each primary flight control: xControls = zLiftDrag * elevatorPosition (pitch) yControls = zLiftDrag * rudderPosition (yaw) zControls = zLiftDrag * aileronPosition (roll) It also implements the "instant centre" feature for the aileron (roll) and the ground steering controls (the latter is controlled by using the rudder keys when on the ground). This feature is for keyboard users only, and instantly centres the control when you press the key for the opposite direction, so if we press "S" to roll left, then pressing "D" will instantly centre the joystick before rolling to the right. This feature does not apply to the elevator or rudder, though it does apply to the rudder controls when on the ground, as they double-up as brake controls for ground steering, which does have this feature. Arguments: L The current value of onGround: * 0 = we are not on the ground * 1 = we are on the ground
.ApplyFlightControl LDX #2 \ Set a counter in X to work through the three axes, so \ we can work our way through the three primary flight \ controls as follows: \ \ * 2 = aileron, for roll around the z-axis \ * 1 = rudder, for yaw around the y-axis \ * 0 = elevator, for pitch around the x-axis \ \ We also work through the aileron, rudder and elevator \ key pairs, whose values are stored in these key logger \ offsets in (keyLoggerHi keyLoggerLo), to check \ whether any of the relevant control keys are being \ pressed \ \ We set a counter in X to count down through these \ index values, from 2 to 1 to 0 .fcon1 LDA elevatorPosition,X \ Fetch the position of the flight control that affects BEQ fcon7 \ the axis we are currently processing LDY keyLoggerLo,X \ Fetch the low byte for this key pair, which will be 1 \ if a key is being pressed, or 0 if no key is pressed BNE fcon3 \ If Y is non-zero then a key in this key pair is being \ pressed, so jump down to fcon3 TAY \ No key is being pressed for this axis, so copy the \ current position of the flight control into Y BMI fcon2 \ If the control's current position is negative then \ jump to fcon2 CPY #4 \ If the control's current position >= 4, jump to fcon6 BCS fcon6 \ to set the control's position to A, which will make no \ difference as A already contains the current value BCC fcon5 \ The control's current position < 4, so jump to fcon5 \ to zero the control (this BCC is effectively a JMP as \ we just passed through a BCS) .fcon2 \ If we get here then the control's current position in \ Y is negative CPY #&FD \ If the control's current position >= -3, jump to fcon5 BCS fcon5 \ to zero the control BCC fcon6 \ The control's current position < -3, so jump to fcon6 \ to set the control's position to A, which will make no \ difference as A already contains the current value \ (this BCC is effectively a JMP as we just passed \ through a BCS) .fcon3 \ If we get here then a key is being pressed for this \ control and A contains the control's current position CPX #1 \ If the axis in X < 1, then an elevator key is being BCC fcon7 \ pressed, so jump to fcon7 to leave the contol's \ position alone BNE fcon4 \ If the axis in X <> 0, then an aileron key is being \ pressed, so jump to fcon4 to check whether to apply \ the aileron's "instant centre" feature \ If we get here then a rudder key is being pressed LDY L \ Fetch the current value of onGround BEQ fcon7 \ If onGround is zero then we are not on the ground, so \ jump to fcon7 to leave the contol's position alone, \ otherwise keep going to check whether to apply the \ ground steering's "instant centre" feature .fcon4 \ If we get here then either an aileron key is being \ pressed, or we are on the ground and a rudder key is \ being pressed \ \ Pressing the rudder key while on the ground controls \ ground steering, by applying the brakes to the \ individual wheels EOR keyLoggerHi,X \ The relevant entry in keyLoggerHi will be -1 or +1 \ depending on the direction of the aileron or rudder \ key being applied, so this EOR compares the key's \ direction with the current position, setting bit 7 \ if the two have different signs, and clearing bit 7 \ if they have the same sign BPL fcon7 \ If bit 7 is clear, then the key's direction and the \ current position of the control have the same sign, so \ jump to fcon7 to leave the contol's position alone \ \ Otherwise we are pressing a key in the opposite \ direction to the current aileron or ground steering \ position, so we instantly move the control back to the \ centre point .fcon5 \ We jump here if control's current position is: \ \ * Positive and < 4 \ * Negative and >= -3 \ \ i.e. -3 <= position <= 3 \ \ In either case, we set the position to 0, so this \ implements a dead zone around the control's centre \ point, and the "instant centre" feature for the \ aileron and ground steering LDA #0 \ Set A = 0 to set as the control's new position, i.e. \ centre the control .fcon6 STA elevatorPosition,X \ Set the control's new position to the value in A .fcon7 LDA elevatorPosition,X \ Fetch the updated position of the flight control for \ the current axis BPL fcon8 \ If the control's new position is positive, jump to \ fcon8 to skip the following EOR #&FF \ Negate A using two's complement, so: CLC \ ADC #1 \ A = |A| \ = |controlPosition| .fcon8 STA R \ Set R = |A| \ = |controlPosition| LDY zLiftDragLo \ Set (A Y) = zLiftDrag LDA zLiftDragHi JSR Multiply8x16-6 \ Store X in VV and set: \ \ (G W V) = (A Y) * R \ = zLiftDrag * |controlPosition| \ \ Also set A to the high byte of the result, so (A W V) \ also contains the result LDX VV \ Retrieve X from VV so it once again contains the axis \ index LDY elevatorPosition,X \ If the position of the flight control is positive, BPL fcon9 \ jump to fcon9 to skip the following SEC \ Negate (G W) and return the high byte in A, so (A W) JSR Negate16Bit \ contains the negated result, so we now have the \ following: \ \ (A W V) = zLiftDrag * controlPosition .fcon9 STA xControlsHi,X \ Set xControls = (A W) LDA W \ = zLiftDrag * controlPosition STA xControlsLo,X DEX \ Decrement the loop counter to move to the next axis BEQ fcon7 \ If this is the elevator axis (X = 0), loop back to \ fcon7 to skip the "instant centre" check, as this \ feature doesn't apply to pitching BPL fcon1 \ If this is the rudder y-axis (X = 1), loop back to \ fcon1 to apply the "instant centre" check, as this \ feature applies to the ground steering RTS \ Return from the subroutine