Skip to navigation

Aviator on the BBC Micro

Dashboard: UpdateIndicator (Part 7 of 15)

Name: UpdateIndicator (Part 7 of 15) [Show more] Type: Subroutine Category: Dashboard Summary: Calculations for the vertical speed indicator (indicator 4) Deep dive: Hard-coded division in the dashboard routines
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file

This section takes the vertical speed from (yVelocityTop yVelocityHi) and reduces it to the range -40 to +40, before passing it to the DrawIndicatorHand routine to update the on-screen vertical speed indicator.
.uind8 \ If we get here then the indicator number in X is 4 LDA yVelocityHi \ Set (A T) = (yVelocityTop yVelocityHi) STA T \ = yVelocity LDA yVelocityTop BPL uind9 \ If the vertical speed is positive, jump down to uind9 LDA #0 \ The vertical speed is negative, so we make it positive SEC \ by calculating: SBC T \ STA T \ (A T) = (0 0) - (A T) \ \ starting with the low bytes LDA #0 \ And then the high bytes SBC yVelocityTop .uind9 \ By this point, (A T) = |yVelocity| LSR A \ Set (A T) = (A T) / 8 ROR T \ = |yVelocity| / 8 LSR A ROR T LSR A ROR T CMP #0 \ If A = 0, so (A T) = (0 T) = T, so jump to uind10 to BEQ uind10 \ skip the following as T contains the correct value of \ |yVelocity| / 8 LDA #255 \ A is non-zero, which means that (A T) > 255, so set STA T \ T = 255 so that T has a maximum value of 255 .uind10 \ At this point, T contains |yVelocity| / 8, capped to a \ maximum value of 255 \ We now calculate A = T * n / 256 with a hardcoded n, \ using unrolled shift-and-add multiplication LDA T \ Set A = T LSR A \ Bit 0 of n is 0 CLC \ Bit 1 of n is 1 ADC T ROR A LSR A \ Bit 2 of n is 0 LSR A \ Bit 3 of n is 0 LSR A \ Bit 4 of n is 0 CLC \ Bit 5 of n is 1 ADC T ROR A LSR A \ Bit 6 of n is 0 \ Bit 7 of n is 0 and the final right shift is missing \ From the above, n = %00100010 (34), so we just \ calculated: \ \ A = (T * n / 256) << 1 \ = (T * 34 / 256) << 1 \ = T * 68 / 256 \ \ which takes |yVelocity| / 8 in the range 0 to 255 \ and reduces it to the range 0 to 68 CMP #40 \ If A < 40, jump to uind11 to skip the following BCC uind11 \ instruction LDA #40 \ Set A = 40, so A has a maximum of 40 and is now in the \ range 0 to 40 .uind11 BIT yVelocityTop \ If the top byte in yVelocityTop is positive (and BPL uind12 \ therefore so is the vertical speed), jump to uind12 to \ skip the following STA T \ Negate the value in A by calculating: LDA #0 \ SEC \ A = 0 - A SBC T \ So by now, A is in the range -40 to +40 \ \ In terms of the original value of yVelocity, this \ means that: \ \ yVelocity / 8 * (68 / 256) = A \ \ so: \ \ yVelocity = A * (256 / 68) * 8 \ = A * 2048 / 68 \ \ If A is 40 then this shows as a vertical speed of \ 4000 feet per minute on the indicator, so if v is the \ vertical speed in feet per minute, A = v / 100, and: \ \ yVelocity = A * 2048 / 68 \ = (v / 100) * 2048 / 68 \ = v * 2048 / 6800 \ = v * 128 / 425 \ \ so yVelocity is stored as 128 / 425 * the vertical \ speed in feet per minute .uind12 JMP DrawIndicatorHand \ Apply min and max limits to the value in A and update \ the indicator on-screen, returning from the subroutine \ using a tail call