irq: Print errors to stderr
[simavr] / examples / board_ledramp / atmega48_ledramp.c
1 /*
2         atmega48_ledramp.c
3         
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <avr/io.h>
23 #include <avr/interrupt.h>
24 #include <avr/sleep.h>
25
26 // for linker, emulator, and programmer's sake
27 #include "avr_mcu_section.h"
28 AVR_MCU(F_CPU, "atmega48");
29
30 #include <stdio.h>
31 /* ------------------------------------------------------------------------- */
32 static int uart_putchar(char c, FILE *stream) {
33   if (c == '\n')
34     uart_putchar('\r', stream);
35   loop_until_bit_is_set(UCSR0A, UDRE0);
36   UDR0 = c;
37   return 0;
38 }
39
40 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
41                                          _FDEV_SETUP_WRITE);
42
43 #define TICK_HZ                                 64
44
45 volatile uint32_t tickCount;
46
47 ISR(TIMER2_COMPA_vect)          // handler for Output Compare 1 overflow interrupt
48 {
49         sei();
50         tickCount++;
51 }
52
53 void tick_init()
54 {
55         /*
56                 Timer 2 as RTC
57          */
58         // needs to do that before changing the timer registers
59         // ASYNC timer using a 32k crystal
60         ASSR |= (1 << AS2);
61         TCCR2A = (1 << WGM21);
62     // use CLK/8 prescale value, clear timer/counter on compareA match
63     TCCR2B = (2 << CS20);
64  /*   -- MathPad
65                 clock=32768
66                 prescaler=8
67                 hz=64
68                 (clock/prescaler/hz)-1:63 -- */
69     OCR2A = 63;
70     TIMSK2  |= (1 << OCIE2A);
71 }
72
73 volatile uint8_t pressed = 0;
74
75 ISR(PCINT1_vect)
76 {
77         pressed = (PINC & (1 << PC0)) ? 0 : 1;
78         // wouldn't do that on real hardware, but it's a demo...
79         printf("PCINT1_vect %02x\n", PINC);
80 }
81
82 int main()
83 {       
84         DDRB=0xff;      // all PORT B output
85         DDRC = 0;       // make PORT C input
86         // enable pin change interrupt for PORT C pin 0
87         PCMSK1 |= (1 << PCINT8);        // C0
88         PCICR |= (1 << PCIE1);
89
90         stdout = &mystdout;
91         
92         tick_init();
93         sei();
94
95         uint8_t mask = 0;
96         for (;;) {
97                 mask <<= 1;
98                 if (!mask)
99                         mask = 1;
100                 if (pressed)
101                         PORTB = 0xff;
102                 else
103                         PORTB = mask;
104                 sleep_mode();
105         }       
106 }
107