1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 |
|
4 | // ----- Pin maps (see scematics) -----
|
5 | #define SATELIT_CLK PA1
|
6 |
|
7 | // ----- Makros -----
|
8 | #define FASTER_CLK_ON PORTA |= (1<<SATELIT_CLK) // high
|
9 | #define FASTER_CLK_OFF PORTA &= ~(1<<SATELIT_CLK) // low
|
10 |
|
11 | // ----- Timer -----
|
12 | // number of clockcycles of equal length *2 you want to insert between to clock cycles on ICP1 input capture pin
|
13 | #define CLK_multiplier_times_2 8
|
14 |
|
15 | void Toggle_Clock(void)
|
16 | {
|
17 | // static variables for faster access compared to global
|
18 | static unsigned int full_interval_length = 0;
|
19 | static char Pin_level_state = 0;
|
20 | static char Clock_state = 0;
|
21 | static unsigned int timing_vector[CLK_multiplier_times_2];
|
22 |
|
23 | // Toggle faster clock
|
24 | if (Pin_level_state){
|
25 | FASTER_CLK_OFF;
|
26 | Pin_level_state = 0;
|
27 | }
|
28 | else{
|
29 | FASTER_CLK_ON;
|
30 | Pin_level_state = 1;
|
31 | }
|
32 |
|
33 | if (Clock_state == 0){
|
34 | // new cycles starts
|
35 | // prepare timing vector
|
36 | // read measured interval length between two slower clock pulses
|
37 | full_interval_length = ICR1;
|
38 |
|
39 | char rest = full_interval_length % 8;// rest of division by 8
|
40 |
|
41 | timing_vector[0] = (1*full_interval_length)/CLK_multiplier_times_2;
|
42 | timing_vector[1] = (2*full_interval_length)/CLK_multiplier_times_2;
|
43 | timing_vector[2] = (3*full_interval_length)/CLK_multiplier_times_2;
|
44 | timing_vector[3] = (4*full_interval_length)/CLK_multiplier_times_2;
|
45 | timing_vector[4] = (5*full_interval_length)/CLK_multiplier_times_2;
|
46 | timing_vector[5] = (6*full_interval_length)/CLK_multiplier_times_2;
|
47 | timing_vector[6] = (7*full_interval_length)/CLK_multiplier_times_2;
|
48 | timing_vector[7] = 0xFFFE;// Dummy, timer should never reach this value. external slower clock ISR should appear before this happens.
|
49 |
|
50 | // divide rest of division "equaly" over the timers
|
51 | if (rest == 1){
|
52 | timing_vector[3]++;
|
53 | }
|
54 | else if (rest == 2){
|
55 | timing_vector[2]++;
|
56 | timing_vector[4]++;
|
57 | }
|
58 | else if (rest == 3){
|
59 | timing_vector[1]++;
|
60 | timing_vector[3]++;
|
61 | timing_vector[5]++;
|
62 | }
|
63 | else if (rest == 4){
|
64 | timing_vector[0]++;
|
65 | timing_vector[2]++;
|
66 | timing_vector[4]++;
|
67 | timing_vector[6]++;
|
68 | }
|
69 | else if (rest == 5){
|
70 | timing_vector[0]++;
|
71 | timing_vector[1]++;
|
72 | timing_vector[3]++;
|
73 | timing_vector[5]++;
|
74 | timing_vector[6]++;
|
75 | }
|
76 | else if (rest == 6){
|
77 | timing_vector[0]++;
|
78 | timing_vector[1]++;
|
79 | timing_vector[2]++;
|
80 | timing_vector[4]++;
|
81 | timing_vector[5]++;
|
82 | timing_vector[6]++;
|
83 | }
|
84 | else if (rest == 7){
|
85 | timing_vector[0]++;
|
86 | timing_vector[1]++;
|
87 | timing_vector[2]++;
|
88 | timing_vector[3]++;
|
89 | timing_vector[4]++;
|
90 | timing_vector[5]++;
|
91 | timing_vector[6]++;
|
92 | }
|
93 | }
|
94 |
|
95 | OCR1A = timing_vector[Clock_state];// set time for next satellite clk event
|
96 |
|
97 | Clock_state++; // increment faster clk cycle counter
|
98 | if (Clock_state == 8){
|
99 | Clock_state = 0; // reset cycle
|
100 | }
|
101 |
|
102 | // it is necessary to reach end of this before "timing_vector[Clock_state]" MCU cycles
|
103 | }
|
104 |
|
105 | ISR(TIMER1_CAPT_vect)
|
106 | {
|
107 | // ICR1 is set to TCNT1 by hardware.
|
108 | TCNT1 = 0; // reset current value of timer 1.
|
109 | Toggle_Clock(); // Toggle faster clock
|
110 | }
|
111 |
|
112 | ISR(TIMER1_COMPA_vect)
|
113 | {
|
114 |
|
115 | OCR1A = 0xFFFE;// Dummy 16-bit access that "should" take as long as TCNT1 = 0;.Timer should never reach this value.
|
116 | Toggle_Clock(); // Toggle faster clock
|
117 | }
|
118 |
|
119 | int main(void)
|
120 | {
|
121 | // ----- Hardware -----
|
122 | // GPIOs
|
123 | FASTER_CLK_OFF;
|
124 | DDRA |= (1 << SATELIT_CLK);
|
125 |
|
126 | // ----- Timer 1 -----
|
127 | TCCR1B |= (1<<ICES1); // Trigger positive edge
|
128 |
|
129 | //CS12 CS11 CS10 Description
|
130 | //0 0 0 No clock source (Timer/Counter stopped).
|
131 | //0 0 1 clkI/O/1 (No prescaling)
|
132 | //0 1 0 clkI/O/8 (From prescaler)
|
133 | //0 1 1 clkI/O/64 (From prescaler)
|
134 | //1 0 0 clkI/O/256 (From prescaler)
|
135 | //1 0 1 clkI/O/1024 (From prescaler)
|
136 | //1 1 0 External clock source on T1 pin. Clock on falling edge.
|
137 | //1 1 1 External clock source on T1 pin. Clock on rising edge.
|
138 |
|
139 | // prescaler = 1
|
140 | //TCCR1B |= (1<<CS12);
|
141 | TCCR1B &= ~(1 <<CS12);
|
142 | //TCCR1B |= (1<<CS11);
|
143 | TCCR1B &= ~(1 <<CS11);
|
144 | TCCR1B |= (1<<CS10);
|
145 | //TCCR1B &= ~(1 <<CS10);
|
146 |
|
147 | OCR1A = 0xFFFE; // Dummy, should never be reached - if slower clock is present
|
148 |
|
149 | // integrate overflow ISR depending on what you wnat to do when no slow clock is present
|
150 | //TIMSK &= ~(1 <<TOIE1); // overflow ISR
|
151 | TIMSK |= (1 <<ICIE1 ); // Input Capture Interrupt Enable
|
152 | TIMSK |= (1 <<OCIE1A); // compare A match enable
|
153 | while(1){}
|
154 | }
|