1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #include <avr/pgmspace.h>
|
4 | #include <util/delay.h>
|
5 |
|
6 | #ifndef F_CPU
|
7 | #define F_CPU 4000000UL //external clock from STK500
|
8 | #endif
|
9 |
|
10 | // 9600 baud
|
11 | #define UART_BAUD_RATE 9600
|
12 | /** Size of the circular receive buffer, must be power of 2 */
|
13 | #ifndef UART_RX_BUFFER_SIZE
|
14 | #define UART_RX_BUFFER_SIZE 32
|
15 | #endif
|
16 | /** Size of the circular transmit buffer, must be power of 2 */
|
17 | #ifndef UART_TX_BUFFER_SIZE
|
18 | #define UART_TX_BUFFER_SIZE 32
|
19 | #endif
|
20 |
|
21 | /* test if the size of the circular buffers fits into SRAM */
|
22 | #if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) )
|
23 | #error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"
|
24 | #endif
|
25 |
|
26 | /*
|
27 | ** high byte error return code of uart_getc()
|
28 | */
|
29 | #define UART_FRAME_ERROR 0x0800 // Framing Error by UART
|
30 | #define UART_OVERRUN_ERROR 0x0400 // Overrun condition by UART
|
31 | #define UART_BUFFER_OVERFLOW 0x0200 // receive ringbuffer overflow
|
32 | #define UART_NO_DATA 0x0100 // no receive data available
|
33 |
|
34 | /*
|
35 | * constants and macros
|
36 | */
|
37 | #define UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ((F_CPU)/((UART_BAUD_RATE)*16l)-1)
|
38 |
|
39 |
|
40 | // size of RX/TX buffers
|
41 | #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
|
42 | #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
|
43 |
|
44 | #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
|
45 | #error RX buffer size is not a power of 2
|
46 | #endif
|
47 | #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
|
48 | #error TX buffer size is not a power of 2
|
49 | #endif
|
50 |
|
51 | #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV
|
52 | #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA
|
53 | #define UART0_STATUS USR
|
54 | #define UART0_CONTROL UCR
|
55 | #define UART0_DATA UDR
|
56 | #define UART0_UDRIE UDRIE
|
57 |
|
58 |
|
59 | // module global variables
|
60 |
|
61 | static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
|
62 | static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
|
63 | static volatile unsigned char UART_TxHead;
|
64 | static volatile unsigned char UART_TxTail;
|
65 | static volatile unsigned char UART_RxHead;
|
66 | static volatile unsigned char UART_RxTail;
|
67 | static volatile unsigned char UART_LastRxError;
|
68 |
|
69 |
|
70 | SIGNAL(UART0_RECEIVE_INTERRUPT)
|
71 | //*************************************************************************
|
72 | //Function: UART Receive Complete interrupt
|
73 | //Purpose: called when the UART has received a character
|
74 | //**************************************************************************
|
75 | {
|
76 | unsigned char tmphead;
|
77 | unsigned char data;
|
78 | unsigned char usr;
|
79 | unsigned char lastRxError;
|
80 |
|
81 |
|
82 | /// read UART status register and UART data register
|
83 | usr = UART0_STATUS;
|
84 | data = UART0_DATA;
|
85 |
|
86 | //calculate buffer index
|
87 | tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
|
88 |
|
89 | if ( tmphead == UART_RxTail ) {
|
90 | // error: receive buffer overflow
|
91 | lastRxError = UART_BUFFER_OVERFLOW >> 8;
|
92 | }else{
|
93 | // store new index
|
94 | UART_RxHead = tmphead;
|
95 | // store received data in buffer
|
96 | UART_RxBuf[tmphead] = data;
|
97 | }
|
98 | UART_LastRxError = lastRxError;
|
99 | }
|
100 |
|
101 |
|
102 | SIGNAL(UART0_TRANSMIT_INTERRUPT)
|
103 | //*************************************************************************
|
104 | //Function: UART Data Register Empty interrupt
|
105 | //Purpose: called when the UART is ready to transmit the next byte
|
106 | //**************************************************************************
|
107 | {
|
108 | unsigned char tmptail;
|
109 |
|
110 |
|
111 | if ( UART_TxHead != UART_TxTail) {
|
112 | // calculate and store new buffer index
|
113 | tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
|
114 | UART_TxTail = tmptail;
|
115 | // get one byte from buffer and write it to UART
|
116 | UART0_DATA = UART_TxBuf[tmptail]; // start transmission
|
117 | }else{
|
118 | // tx buffer empty, disable UDRE interrupt
|
119 | UCSRB |= (0<<UDRIE);
|
120 |
|
121 | //UART0_CONTROL &= ~_BV(UART0_UDRIE);
|
122 | }
|
123 | }
|
124 |
|
125 |
|
126 | //*************************************************************************
|
127 | //Function: uart_init()
|
128 | //Purpose: initialize UART and set baudrate
|
129 | //Input: baudrate using macro UART_BAUD_SELECT()
|
130 | //Returns: none
|
131 | //**************************************************************************
|
132 | void uart_init(unsigned int baudrate)
|
133 | {
|
134 | UART_TxHead = 0;
|
135 | UART_TxTail = 0;
|
136 | UART_RxHead = 0;
|
137 | UART_RxTail = 0;
|
138 |
|
139 | UBRRH = (unsigned char)(baudrate>>8);
|
140 | UBRRL = (unsigned char) baudrate;
|
141 |
|
142 | //Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size
|
143 |
|
144 | UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|
|
145 |
|
146 | (0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);
|
147 |
|
148 | //Enable Transmitter and Receiver and Interrupt on receive complete
|
149 |
|
150 | UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
|
151 |
|
152 | }// uart_init
|
153 |
|
154 |
|
155 | //*************************************************************************
|
156 | //Function: uart_putc()
|
157 | //Purpose: write byte to ringbuffer for transmitting via UART
|
158 | //Input: byte to be transmitted
|
159 | //Returns: none
|
160 | //**************************************************************************
|
161 | void uart_putc(unsigned char data)
|
162 | {
|
163 | unsigned char tmphead;
|
164 |
|
165 | while (!(UCSRA & (1<<UDRE))); // Do nothing until data have been
|
166 | //transmited
|
167 | tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
|
168 |
|
169 | while ( tmphead == UART_TxTail ){
|
170 | ;// wait for free space in buffer
|
171 | }
|
172 |
|
173 | UART_TxBuf[tmphead] = data;
|
174 | UART_TxHead = tmphead;
|
175 | UART0_DATA = UART_TxBuf[tmphead]; // Put data into Buffer, sends the
|
176 | //data
|
177 | _delay_ms(10);
|
178 | // enable UDRE interrupt
|
179 | UCSRB |= (1<<UDRIE);
|
180 |
|
181 | }// uart_putc
|
182 |
|
183 | /* command sequences im EEPROM (first program Flash, then EEPROM) */
|
184 | unsigned char eeMenue[] EEMEM = { 0x02, 0x21, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x9D, 0x2A };
|
185 | unsigned char eeExit[] EEMEM = { 0x02, 0x21, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5C, 0x2A };
|
186 |
|
187 | unsigned int c, iState;
|
188 | char cSend;
|
189 |
|
190 | /* Sends a 19 character command found in EEPROM */
|
191 | void SendCommand(unsigned int iNo)
|
192 | {
|
193 | unsigned i;
|
194 | for (i = 19 * iNo; i <= 19 * iNo + 18; i++ )
|
195 | {
|
196 | cSend = eeprom_read_byte(&eeMenue[i]);
|
197 | uart_putc(cSend);
|
198 | }
|
199 | }
|
200 |
|
201 | int main(void)
|
202 | {
|
203 |
|
204 | PORTD = 0x0C; // pull ups for key inputs PortD2 and portD3
|
205 | DDRC = 0x03; // outputs for LEDs
|
206 | PORTC = 0x03; /( LEDs off
|
207 |
|
208 | /*
|
209 | * Initialize UART library, pass baudrate and AVR cpu clock
|
210 | * with the macro
|
211 | * UART_BAUD_SELECT() (normal speed mode )
|
212 | */
|
213 | uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
|
214 |
|
215 | /*
|
216 | * now enable interrupt, since UART library is interrupt controlled
|
217 | */
|
218 | sei();
|
219 |
|
220 |
|
221 | iState = 0;
|
222 | for(;;)
|
223 | {
|
224 | if (iState != PIND) /* Key state changed ? */
|
225 | {
|
226 | _delay_ms(50);
|
227 | if ((PIND & 0x08) == 0x00) /* one key */
|
228 | {
|
229 | PORTC = 1;
|
230 | SendCommand(0);
|
231 | }
|
232 | else
|
233 | {
|
234 | if ((PIND & 0x0C) == 0x0C) /* no key */
|
235 | PORTC = 3;
|
236 | }
|
237 | iState = PIND;
|
238 | _delay_ms(2000); /* dirty "debounce" */
|
239 | }
|
240 | }
|
241 | return 0;
|
242 | }
|