-
Notifications
You must be signed in to change notification settings - Fork 0
/
single_synch_byte.c
187 lines (163 loc) · 5.54 KB
/
single_synch_byte.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief
* Implementation of the single synch byte method.
*
* This file contain the implementation of the single SYNCH byte
* synchronization method. The UART RXC interrupt service routine (ISR) is
* a part of this implementation. To implement a communication protocol,
* code to handle reception of UART data must be added in this file or
* double_synch_byte.c depending on which method is used.
*
* \par Application note:
* AVR054 Synchronization of the internal RC oscillator
*
* \par Documentation:
* For comprehensive code documentation, supported compilers, compiler
* settings and supported devices see readme.html
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: [email protected] \n
*
* $Name: RELEASE_1_2 $
* $Revision: 1.3 $
* $RCSfile: single_synch_byte.c,v $
* $Date: 2006/02/17 11:47:59 $ \n
******************************************************************************/
#include "online_synch.h"
#include "device_specific.h"
#include <ioavr.h>
#include <inavr.h>
#if defined(SYNCH_METHOD_SINGLE_SYNCH_BYTE)
extern unsigned char breakDetected;
extern unsigned char calStep;
extern unsigned char synchState; // First set to SS_MEASURING within PREPARE_FOR_SYNCH() routine.
unsigned char defaultOSCCAL;
void Initialize_Synchronization(void)
{
// Initialize UART.
SYNCH_USART_STATCTRL_REG_B |= (1 << SYNCH_RXEN) | (1 << SYNCH_RXCIE);
SYNCH_UBRRH = (SYNCH_UBRR >> 8); //Set baud rate registers
SYNCH_UBRRL = (SYNCH_UBRR & 0x00ff);
// Set INT0 pin as input, no internal pullup.
DDR_INT0 &= ~(1 << PIN_NUMBER_INT0);
PORT_INT0 &= ~(1 << PIN_NUMBER_INT0);
// If 8 bit timer is used, it must be started here.
#if ! defined(NINE_BIT_TIMER)
SYNCH_TIMER_PRESCALER_REGISTER |= (1 << CS00); // Timer/Counter1 runs at fclk. (no prescaling)
#endif
// Read default OSCCAL value from EEPROM.
while(EECR & (1 << EEPROM_WRITE_ENABLE))
{ // Wait if EEPROM is busy writing
}
EEAR = DEFAULT_OSCCAL_ADDRESS;
EECR |= (1 << EERE);
defaultOSCCAL = EEDR;
}
#pragma vector=SYNCH_USART_RXC_vect
__interrupt void UART_RXC_ISR(void)
{
unsigned char temp;
if (SYNCH_USART_STATCTRL_REG_A & (1 << SYNCH_FE)) // Frame error has occured.
{
PREPARE_FOR_SYNCH();
}
else
{
// Process character received by UART receiver.
// It is necessary that the UART data register is read at this point
// to clear the receive buffer. If the value read is not used, the
// compiler will optimize away the reading of UART data register. In
// this case the synchronization will not work.
temp = SYNCH_UDR;
PORTB = temp;
}
}
// Force no optimization for this ISR.
// If this is changed, the timing will not be correct.
#pragma optimize=z 2
#pragma vector=SYNCH_EXT_INT_vect
__interrupt void SYNCH_EXT_INT_ISR(void)
{
#if defined(NINE_BIT_TIMER)
unsigned int cycleCount;
#else
unsigned char cycleCount;
#endif
#if defined(NINE_BIT_TIMER)
// Stop Timer/Counter0.
SYNCH_TIMER_PRESCALER_REGISTER &= ~((1 << CS02) | (1 << CS01) | (1 << CS00));
// Read Timer/Counter0.
cycleCount = TCNT0; // Retrieve the low 8 bits.
// Use the overflow flag as the high bit of a 9-bit timer.
cycleCount |= ((SYNCH_TIMER_INT_FLAG_REGISTER & (1 << TOV0)) << (8 - TOV0));
// Reset Timer/Counter0.
TCNT0 = 0;
SYNCH_TIMER_INT_FLAG_REGISTER = (1 << TOV0); // Clear overflow flag.
// Start Timer/Counter0.
SYNCH_TIMER_PRESCALER_REGISTER = (1 << CS00); // Timer/Counter1 runs at fclk. (no prescaling)
#else
// Read Timer/Counter0.
cycleCount = TCNT0;
// Reset Timer/Counter0.
TCNT0 = 0;
#endif
if (breakDetected)
{
switch(synchState) {
case (SS_MEASURING):
{
//Set external interrupt 0 to trigger on rising edge.
SET_INT0_RISING();
synchState = SS_BINARY_SEARCH;
break;
}
case (SS_BINARY_SEARCH):
{
if ( cycleCount > COUNT_HIGH_LIMIT)
{
OSCCAL -= calStep;
NOP();
}
else if ( cycleCount < COUNT_LOW_LIMIT)
{
OSCCAL += calStep;
NOP();
}
else
{
// Within limits, do nothing.
}
calStep >>= 1; // Divide by 2.
if (calStep == 0)
{
// Binary search complete. Clean up, and exit.
breakDetected = FALSE;
// Enable UART receiver.
SYNCH_USART_STATCTRL_REG_B |= (1 << SYNCH_RXEN);
// Disable INT0 (external interrupt 0)
DIS_INT0();
}
else
{
//Set external interrupt 0 to trigger on falling edge.
SET_INT0_FALLING();
synchState = SS_MEASURING;
}
break;
}
}
return;
}
else // breakDetected = FALSE
{
// Disable sleep flag. (Ensures that the device
// does not enter any sleep mode unintended.)
MCUCR &= ~(1 << SE);
PREPARE_FOR_SYNCH();
return;
}
}
#endif