]> www.fi.muni.cz Git - kolektor.git/blob - main.c
Initial commit
[kolektor.git] / main.c
1 #include <avr/io.h>
2 #include <util/delay.h>
3 #include <avr/sleep.h>
4 #include <avr/interrupt.h>
5 #include <avr/power.h>
6
7 #include "logging.h"
8
9 // init PLL clock for timer/counter 1
10 // datasheet sekce 12.2.1
11 static void enable_pll_clock()
12 {
13         // async clock
14         PLLCSR = _BV(PLLE) | _BV(LSM); // low-speed mode (32 MHz)
15
16         // Synchronize to the phase lock
17         _delay_us(100);
18         while((PLLCSR & _BV(PLOCK)) == 0)
19                 ;
20         PLLCSR |= _BV(PCKE);
21 }
22
23 // Timer/Counter 1 initialization
24 // datasheet sekce 12
25 static void init_tc1()
26 {
27         power_timer1_enable();
28
29         TCCR1 = _BV(CTC1) // clear on compare match
30                 | _BV(CS10) // clock = PCK (no divisor)
31                 | _BV(COM1A1) // clear output line on compare match
32                 | _BV(PWM1A); // PWM mode
33
34         OCR1C = 255;    // TOP value
35
36         DDRB |= _BV(PB1);
37         OCR1A = 0;      // stride
38         
39         // Tohle pripadne povoli PWM i na OC1B (PB4)
40         // GTCCR = _BV(COM1B1) | _BV(PWM1B);
41         // DDRB |= _BV(PB4);
42         // OCR1B = 0; // stride
43 }
44
45 // precte synchronne (busy-waitem) jednu hodnotu z A/D prevodniku
46 static uint16_t read_adc_sync()
47 {
48         uint16_t rv;
49
50         ADCSRA |= _BV(ADSC); // start the conversion
51
52         // wait for the conversion to finish
53         while((ADCSRA & _BV(ADIF)) == 0)
54                 ;
55
56         rv = ADCW;
57         ADCSRA |= _BV(ADIF); // clear the IRQ flag
58
59         return rv;
60 }
61
62 // analog to digital converter
63 // datasheet sekce 17
64 static void init_adc()
65 {
66         power_adc_enable();
67         ACSR |= _BV(ACD); // enable ADC, disable AC
68
69         ADCSRA = _BV(ADEN) // enable
70                 | _BV(ADPS1) | _BV(ADPS0) // CLK/8 = 125 kHz
71                 ;
72
73         DIDR0 = _BV(ADC1D) | _BV(ADC3D); // disable dig. input on ADC1, ADC3 (PB2, PB3)
74         ADMUX = _BV(REFS1) // 1.1V internal reference
75                 | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0) // ADC4 (temperature)
76                 ;
77
78         // do the first conversion, drop the result
79         read_adc_sync();
80 }
81
82 int main(void)
83 {
84         unsigned char i;
85
86         init_log();
87
88         log_byte(0x42); // zkouska logovani
89         log_flush();    // nezapomenout vylit buffer
90
91         power_all_disable(); /* vypneme cele I/O, pak zapneme co bude potreba */
92
93         DDRB |= _BV(DDB4); // PB4 as output
94
95         enable_pll_clock();
96         init_tc1();
97         init_adc();
98
99         // po skonceni inicializace muzeme i zapnout preruseni,
100         // pokud je budeme potrebovat
101         // cli();
102
103         // priklad prace s A/D prevodnikemo
104         // init_adc() necha ADMUX nastaveny na ADC4 (teplomer), jinak
105         // tady lze ADMUX prestavit na neco jineho (pozor na napetovou
106         // referenci REFS)
107         log_word(read_adc_sync()); // nacteme teplotu, zalogujeme
108         // interpretace vysledku: datasheet sekce 17.12
109         log_flush();
110
111         while(1) {
112                 for (i = 0; i < 16; i++) {
113                         // zapiname/vypiname portb4 v sudem/lichem kroku
114                         if (i & 1) {
115                                 PORTB |= _BV(PORTB4);
116                         } else {
117                                 PORTB &= ~_BV(PORTB4);
118                         }
119
120                         // hodnopta PWM pro PB1 (OC1A)
121                         // jdeme od 128 do 248, napriklad:
122                         OCR1A = 0x80 + (i << 3);
123
124                         // busy-wait, nebo se muzeme nechat casovat
125                         // pomoci watchdogu (WDT, datasheet sekce 7.4.5)
126                         // nebo pomoci Timer/Counter 0 (datasheet sekce 11)
127                         _delay_ms(1500);
128                 }
129         }
130 }