306/317
10 - Second Application: a Sailing Computer
ADCSR = ( 1 << ADON ) | DIRECTION_CHANNEL ;
while ( ( ADCSR & ( 1 << COCO ) ) == 0 ) ;
/* Wait for end of
conversion */
/* Correct mounting and take advantage of overflow to roll over. */
a = ADCDR + VaneAdjust ;
/* Configure A to D back to channel 0 (push-buttons) */
ADCSR = ( 1 << ADON ) | PUSHBUTTON_CHANNEL ;
Wiper[Wip+] = a ;
if ( WiperIndex >= FILTER_CELLS )
WiperIndex = 0 ;
/* Loop back to
beginning of array */
/* Compute sum of all readings */
Angle = 0 ;
for ( i = 0 ; i < FILTER_CELLS ; i++ )
Angle += Wiper[i] ;
RawWindDirection = Angle >> ( LOG_FILTER_CELLS - 1 ) ;
/* Assign
result = average * 2 */
}
The new reading is written to a circular buffer made of an array which index is incremented
each time, returning to zero when it has reached the last element. A new average is computed
each time, by summing the values of all elements, and dividing the sum by the number of el-
ements. Actually, since we need to increase the resolution from eight to nine bits, we divide
the sum by only half the number of elements. Since the ST7 has no division instruction, and
the division takes a long time, the solution used here is to have a number of element that is an
exact power of two (32), and we divide by shifting the sum right by 5 bits. This result is written
to the global variable
RawWindDirection
.
10.5.5 The periodic interrupt service routine
This routine does the display refresh each time, and, every other time, the push-button polling
and the vane angle measurement.
#pragma TRAP_PROC SAVE_REGS
void TimerAInterrupt ( void )
{
static Bool Turn ;
asm
{
ld a, TASR ;
/* Clear interrupt request */
ld a, TACLR ;
}