Revs on the BBC Micro

# Dashboard: DrawRevCounter

```       Name: DrawRevCounter                                          [Show more]
Type: Subroutine
Category: Dashboard
Summary: Draw the hand on the rev counter
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* UpdateDashboard calls DrawRevCounter

.DrawRevCounter

LDA #%000              \ Set H = %000 to pass into DrawDashboardLine below
STA H

LDA revCount           \ Set A = revCount, which is the value we want to draw
\ on the rev counter, in the range 0 to 170

CMP #30                \ If A >= 30, skip the following instruction
BCS revs1

LDA #30                \ Set A = 30, so A is always at least 30, and is now in
\ the range 30 to 170 (we do this because the hand on
\ the rev counter doesn't fall all the way back to zero)

.revs1

STA T                  \ Set T = A

LSR A                  \ Set A = A / 2 + T
CLC                    \       = A / 2 + A
ADC T                  \       = 1.5 * A
\       = 1.5 * revCount
\
\ which is in the range 45 to 255

ROR A                  \ Set A = A / 2
\       = 0.75 * revCount
\
\ which is in the range 22 to 127

\ We now convert the value in A to the corresponding
\ position on the dial in terms of which quadrant it's
\ in, and which half of that quadrant, so we can pass
\ the details to the DrawDashboardLine routine

SEC                    \ Set A = A - 76
SBC #76

BCS revs2              \ If the subtraction went past zero, add 152, to get:
\   A = A + 76

\ So for A in the range 22 to 127, this converts:
\
\   A = 22-75  into A = 98-151
\   A = 76-127 into A = 0-51
\
\ If we consider a clock with 0 at 12 o'clock, then 38
\ at 3 o'clock, 76 at 6 o'clock and 114 at 9 o'clock,
\ A is now the position of the hand on that clock, i.e.
\ the position of the hand that we want to draw on the
\ rev counter

.revs2

\ We now calculate the quadrant that contains the hand
\ on the rev counter, numbered 0 to 3 counting clockwise
\ from top-right
\
\ We do this by calculating X = A / 38, by repeatedly
\ subtracting 38 from A until we go past zero

LDX #&FF               \ We start by setting X = -1

SEC                    \ Set the C flag for the subtraction

.revs3

INX                    \ Increment X as we are doing a subtraction

SBC #38                \ Set A = A - 38

BCS revs3              \ If the subtraction didn't take us past zero, loop back
\ to subtract another 38

ADC #38                \ Otherwise add the 38 back that pushed us over the
\ limit, so X now contains the quadrant number, and A
\ contains the remainder (i.e. the fraction that the
\ hand is past the start of the quadrant)

CMP #19                \ If the remainder is < 19, skip the following, as A
BCC revs4              \ contains the distance from the start of quadrant X to
\ the position of the hand (and the C flag is clear)

SBC #19                \ Set A = ~(A - 19) + 20
EOR #&FF               \       = ~(A - 19) + 1 + 19
CLC                    \       = -(A - 19) + 19
ADC #20                \       = 19 - (A - 19)
\
\ so A now contains the distance from the hand to the

SEC                    \ Set the C flag to indicate that A is now the distance
\ from the hand to the end of the quadrant

.revs4

\ By this point:
\
\   X = quadrant number (0 to 3)
\
\   A = distance from start of quadrant to hand (C = 0)
\       distance from hand to end of quadrant   (C = 1)
\
\ where each quadrant is 38 in size, so A is <= 19
\
\ The C flag therefore represents which half of the
\ quadrant the hand is in, 0 denoting the first half and
\ 1 denoting the second half

TAY                    \ Set Y = the distance between the hand and quadrant

STY T                  \ Set T = the distance between the hand and quadrant

TXA                    \ Ensure X is in the range 0 to 3 (it should be, but
AND #3                 \ this makes absolutely sure)
TAX

TXA                    \ This sets bits 1 and 2 of V to the quadrant number,
ROL A                  \ and bit 0 to the C flag, so the possible values are:
STA V                  \
\   * 0 = %000 = Quadrant 0, first half, 12:00 to 1:30
\   * 1 = %001 = Quadrant 0, second half, 1:30 to 3:00
\   * 2 = %010 = Quadrant 1, first half, 3:00 to 4:30
\   * 3 = %011 = Quadrant 1, second half, 4:30 to 6:00
\   * 4 = %100 = Quadrant 2, first half, 6:00 to 7:30
\   * 5 = %101 = Quadrant 2, second half, 7:30 to 9:00
\   * 6 = %110 = Quadrant 3, first half, 9:00 to 10:30
\   * 7 = %111 = Quadrant 3, second half, 10:30 to 12:00
\
\ These are the quadrant values we need to pass to the
\ DrawDashboardLine routine below

AND #%11111100         \ If bit 2 of A is zero, then the hand is in the right
BEQ revs5              \ half of the dial, so jump to revs5 to set W = 0

LDA #7                 \ Otherwise the hand is in the left half of the dial,
\ so set A so we set W = 7 below

.revs5

STA W                  \ Set W = 0 if the hand is in the right half
\         7 if the hand is in the left half
\
\ so we start drawing from the leftmost pixel when
\ drawing to the right, or the rightmost pixel when
\ drawing to the left (which ensures that the hand joins
\ the centre spoke of the rev counter without a gap)

LDA handPixels,Y       \ Set A to the number of pixels that are along the long
\ axis of the hand, given the distance between the hand
\ and quadrant that we set in Y above

STA SS                 \ Set SS to the number of pixels along the long axis

STA U                  \ Set U to the number of pixels along the long axis, to
\ pass through to the DrawDashboardLine routine below

LDA startDialLo,X      \ Set the low byte of (Q P) to the low byte of the
AND #%11111000         \ screen address for the starting point of the hand for
STA P                  \ quadrant Y, which we get from the startDialLo table,
\ and clear bits 0 to 2 so the address points to the
\ top line of the relevant character block

LDA startDialLo,X      \ Set Y to the pixel row within the character block
AND #%00000111         \ for the starting point, which we get from bits 0 to 2
TAY                    \ of the starting point's screen address

LDA startDialHi,X      \ Set the high byte of (Q P) to the high byte of the
STA Q                  \ screen address for the starting point of the hand for
\ quadrant Y, so (Q P) now contains the full address of
\ the starting point's character block

\ Fall through into DrawDashboardLine to draw a line
\ from the starting point given in (Q P) and Y, in the
\ direction given in V, with U pixels along the longest
\ axis, and in the half of the dial given in W
```