267/317
9 - A Carrier-current System for domestIc Remote Control
if ( ( KeyCode&1)==0)
TACR1 |=(1<<OLVL1 ) ; /* Validate pulse for next interrupt */
else
TACR1 &= ~( 1 << OLVL1 ) ; /* Invalidate pulse for next interrupt */
KeyCode >>= 1 ; /* Finished with this bit. Ready for next bit */
The PhaseLockedLoop function.
This function measures the phase shift between the nominal position of the zero crossing and
the start of the 1 ms pulse. According to the difference found, the timer period is increased or
decreased, so as to reduce that difference to the smallest value. Actually, once locked, the pe-
riod will oscillate slightly about the nominal value of the line frequency.
Thecodeisthefollowing:
void PhaseLockedLoop ( void )
{
int Position, Deviation ;
asm
{
ld a, TAIC2HR
ld Position, a
ld a, TAIC2LR
ld Position:1, a
}
/* This assembler code is logically equivalent to : */
/* Position = *((int *) &TAIC2HR) ; get signed value of counter */
/* but the order of reading of the two bytes is important, and C does
*/
/* not give any guarantee regarding the order. Thus assembler is
used. */
Deviation = Position - ( TIMER_A_PERIOD - PULSE_LENGTH ) ;
Deviation >>= 4 ; /* Divide by 16 (feedback coefficient). */
if ( Deviation < -PERIOD_DEVIATION )
Deviation = -PERIOD_DEVIATION ; /* Do not pass either limit,
though. */
else
if ( Deviation > PERIOD_DEVIATION )
Deviation = PERIOD_DEVIATION ;
TimerAPeriod = TIMER_A_PERIOD + Deviation ; /* Alter theoretical
period. */
}
The value captured is read using four in-line assembler statements. This is because the cap-
ture register is defined as two separate 8-bit registers, and because these bytes must be read
in a certain order.