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  | }
  |