File: mh-timer.c

package info (click to toggle)
kuttypy 2.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 37,896 kB
  • sloc: python: 58,651; javascript: 14,686; xml: 5,767; ansic: 2,716; makefile: 453; asm: 254; sh: 48
file content (142 lines) | stat: -rw-r--r-- 3,648 bytes parent folder | download | duplicates (5)
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
/* 
mh-timer.c -- simple functions for handling the Timer/Counter
Author : Ajith Kumar, Inter-University Accelerator Centre, New Delhi. 
License : GNU GPL version 3 or later
Date : 23-Oct-2013
*/

#include <avr/io.h>
#include <avr/interrupt.h>

void sqwave_tc0(uint8_t csb, uint8_t ocrval) 
{
// Set TCCR0 in the CTC mode
  TCCR0 = (1 << WGM01) | (1 << COM00) | csb;	
  OCR0 = ocrval;
  TCNT0 = 0;
  DDRB |= (1 << PB3);
}


void pwm_tc0(uint8_t csb, uint8_t ocrval) 
{
// Set TCCR0 in the Fast PWM mode
  TCCR0 =(1 << WGM01) | (1 << WGM00) | (1 << COM01) | csb;
  OCR0 = ocrval;
  TCNT0 = 0;
  DDRB |= (1 << PB3);
}

void sqwave_tc1(uint8_t csb, uint16_t ocra) 
{
		// This can set very low values of freqency on the output
  TCCR1A = (1 << COM1A0);    // Set TCCR1A in the CTC mode
  TCCR1B = (1 << WGM12) | csb;	
  OCR1A = ocra;     // Output Compare register values
  TCNT1 = 0;
  DDRD |= (1 << PD5);   // Set pin OC1A as output
}

void pwm10_tc1(uint8_t csb, uint16_t ocra) 
{
  TCCR1A = (1 << COM1A1) | (1 << WGM11) |(1 << WGM10);  // Set 10bit PWM mode
  TCCR1B = csb;	
  OCR1A = ocra;     // Output Compare register values
  TCNT1 = 0;
  DDRD |= (1 << PD5);   // Set pin OC1A as output
}

//------------------------- Square wave on TC2 -------------------------

#define FLIMIT  4000000          // 8 MHz clock /2
static uint16_t f[] = {1,8,32,64,128,256,1024};
 
uint32_t set_sqr_tc2(uint32_t freq)  // freq must be from 15  to 100000 Hz, no checking done 
{
	uint32_t tmp;
	uint8_t ocr, k;

	DDRD |= (1 << PD7);    // Make PD7 as output
  	k = 0;
  	while(k < 7) 
  	  {
      tmp = FLIMIT / f[k];	// maximum value for the chosen prescaler
      if (tmp/freq <= 256) 
        {
      	TCCR2 = (1 << WGM21) | (1 << COM20) | (k+1);	// CTC mode
      	ocr = tmp/freq;
      	tmp = tmp/ocr;	// the value actually set
      	if (ocr) 
        	--ocr;
      	OCR2 = ocr;
      	return tmp;
        }
      k = k + 1;
  }
	return 0;  
}



//------------------- Frequency measurement ----------------------------

#define MTIME	250 	// We count 100  on TC0

uint32_t measure_freq(void)
{ 
  volatile uint16_t x, k = 500;
  DDRB &= ~(1 << PB1);      // Timer/Counter1 clock in T1 (PB1) as input
  TCCR1B = (1 << CS12) | (1 << CS11) | (1 << CS10);	// External clock on T1 pin 
  TCNT1 = 0;			    // Clear TCNT1
  while(k--) {x=532; while (x--);}
  TCCR1B = 0;               // Stop counter
  return TCNT1 * 2;         // freq = Counts / 500 mS x 2
}

//----------------------- Time interval measurement--------------------------

volatile uint16_t HIWORD;
ISR(TIMER1_COMPA_vect)	// TIMER1 Compare Match A Interrupt
{
TCNT1 = 0;
++HIWORD;
}

void start_timer()
{
/*
When TCNT1 reaches OCR1A, the ISR will run. It will clear TCNT1 and increment HIWORD.
The total time elapsed between start_timer and get_timer = HIWORD * 50000 + TCNT1
*/
 TCCR1B = (1 << CS11);   // Normal mode, with 1MHz clock
 HIWORD = 0;
 OCR1A = 50000;        
 OCR1B = 0xffff;
 TIMSK = (1 <<  OCIE1A);   // Enable compare match interrupt
 TIFR = (1 << OCF1A); 
 TCNT1 = 0;
 sei();
}

uint32_t read_timer()
{
 uint32_t x;
 
 TCCR1B = 0;    // stop TC1 clock
 x = HIWORD * 50000 + TCNT1;
 cli();
 return x;
}

uint32_t r2ftime(uint8_t bit)  
{
// measures rising edge to falling edge time on any bit of PORTB. If no pulse input, program may go in infinite loop
 
 DDRB &= ~(1 << bit);   // set the selected bit as input, on PORT B   
 while( (PINB & (1 << bit)) != 0 ) ;   // Do nothing until the bit is low
 while( (PINB & (1 << bit)) == 0 ) ;   // Wait for a rising edge
 start_timer();
 while( (PINB & (1 << bit)) != 0 ) ;   // Wait for a falling edge
 return read_timer();
}