Import drv/ modules.
[bertos.git] / drv / ser_avr.c
1 /**
2  * \file
3  * <!--
4  * Copyright 2000 Bernardo Innocenti <bernie@codewiz.org>
5  * Copyright 2003, 2004 Develer S.r.l. (http://www.develer.com/)
6  * All Rights Reserved.
7  * -->
8  *
9  * \version $Id$
10  *
11  * \author Bernardo Innocenti <bernie@develer.com>
12  *
13  * \brief AVR UART and SPI I/O driver
14  */
15
16 /*
17  * $Log$
18  * Revision 1.1  2004/05/23 18:10:11  bernie
19  * Import drv/ modules.
20  *
21  * Revision 1.30  2004/05/19 17:06:11  bernie
22  * Serial TX fill mode
23  *
24  * Revision 1.29  2004/05/16 19:16:46  aleph
25  * Serial always transmitting, first try
26  *
27  * Revision 1.28  2004/05/14 12:09:00  aleph
28  * Fix TX port pull-ups
29  *
30  * Revision 1.27  2004/05/08 13:56:02  aleph
31  * Adapt avr serial driver to new design
32  *
33  * Revision 1.25  2004/04/28 13:42:16  aleph
34  * Serial port fixes
35  *
36  * Revision 1.24  2004/04/08 14:17:27  bernie
37  * Change serial to disable TX when not sending data
38  *
39  * Revision 1.23  2004/04/03 20:39:41  aleph
40  * Remove strobe
41  *
42  * Revision 1.22  2004/03/29 17:01:02  aleph
43  * Add function to set serial parity, fix it when ser_open is used
44  */
45
46 #include "ser.h"
47 #include "ser_p.h"
48 #include "kdebug.h"
49 #include "config.h"
50 #include "hw.h"
51 #include <mware/fifobuf.h>
52
53 extern struct Serial ser_handles[SER_CNT];
54
55 struct AvrSerial
56 {
57         struct SerialHardware hw;
58         struct Serial* serial;
59 };
60
61
62 /* Hardware handshake */
63 #define RTS_ON
64 #define RTS_OFF
65 #define IS_CTS_ON   true
66 #define IS_CTS_OFF  false
67
68
69 /* SPI port and pin configuration */
70 #define SPI_PORT      PORTB
71 #define SPI_DDR       DDRB
72 #define SPI_SCK_BIT   PORTB1
73 #define SPI_MOSI_BIT  PORTB2
74 #define SPI_MISO_BIT  PORTB3
75
76
77 #ifdef __AVR_ATmega103__
78         /* Macro for ATmega103 compatibility */
79         #define UCSR0B UCR 
80         #define UDR0   UDR 
81         #define UCSR0A USR 
82         #define UBRR0L UBRR
83 #else
84         #define UCR  UCSR0B 
85         #define UDR  UDR0  
86         #define USR  UCSR0A 
87 #endif
88
89
90 /* Transmission fill byte */
91 #define SER_FILL_BYTE 0xAA
92
93
94 static void uart0_enabletxirq(UNUSED(struct SerialHardware *ctx))
95 {
96 #ifdef CONFIG_SER_TXFILL
97         UCSR0B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN) | BV(UCSZ2);
98 #else
99         UCSR0B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
100 #endif
101 }
102
103 static void uart0_init(struct SerialHardware *_hw, struct Serial *ser)
104 {
105         struct AvrSerial *hw = (struct AvrSerial *)_hw;
106         hw->serial = ser;
107
108         /* Set TX port as input with pull-up enabled to avoid
109          * noise on the remote RX when TX is disabled */
110         cpuflags_t flags;
111         DISABLE_IRQSAVE(flags);
112         DDRE &= ~BV(PORTE1);
113         PORTE |= BV(PORTE1);
114         ENABLE_IRQRESTORE(flags);
115
116         /* TODO: explain why TX is disabled whenever possible */
117 #ifdef CONFIG_SER_TXFILL
118         /*!
119          * Set multiprocessor mode and 9 bit data frame.
120          * The receiver keep MPCM bit always on. When useful data
121          * is trasmitted the ninth bit is set. Receiver consider the
122          * frame as address info and receive it.
123          * When useless fill bytes are sent the ninth bit is cleared
124          * and the receiver will ignore them, avoiding useless triggering
125          * of RXC interrupt.
126          */
127         UCSR0A = BV(MPCM);
128         UCSR0B = BV(RXCIE) | BV(RXEN) | BV(UCSZ2);
129 #else
130         UCSR0B = BV(RXCIE) | BV(RXEN);
131 #endif
132
133         RTS_ON;
134 }
135
136 static void uart0_cleanup(UNUSED(struct SerialHardware *ctx))
137 {
138         UCSR0B = 0;
139 }
140
141 static void uart0_setbaudrate(UNUSED(struct SerialHardware *ctx), unsigned long rate)
142 {
143         // Compute baud-rate period
144         uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
145
146 #ifndef __AVR_ATmega103__
147         UBRR0H = (period) >> 8;
148 #endif
149         UBRR0L = (period);
150 }
151
152
153 #ifndef __AVR_ATmega103__
154
155 static void uart1_enabletxirq(UNUSED(struct SerialHardware *ctx))
156 {
157         UCSR1B = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
158 }
159
160 static void uart1_init(struct SerialHardware *_hw, struct Serial *ser)
161 {
162         struct AvrSerial *hw = (struct AvrSerial *)_hw;
163         hw->serial = ser;
164
165         /* Set TX port as input with pull-up enabled to avoid
166          * noise on the remote RX when TX is disabled */
167         cpuflags_t flags;
168         DISABLE_IRQSAVE(flags);
169         DDRD &= ~BV(PORTD3);
170         PORTD |= BV(PORTD3);
171         ENABLE_IRQRESTORE(flags);
172
173         /* TODO: explain why TX is disabled whenever possible */
174         UCSR1B = BV(RXCIE) | BV(RXEN);
175
176         RTS_ON;
177 }
178
179 static void uart1_cleanup(UNUSED(struct SerialHardware *ctx))
180 {
181         UCSR1B = 0;
182 }
183
184 static void uart1_setbaudrate(UNUSED(struct SerialHardware *ctx), unsigned long rate)
185 {
186         // Compute baud-rate period
187         uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
188
189         UBRR1H = (period) >> 8;
190         UBRR1L = (period);
191 }
192
193 static void uart0_setparity(UNUSED(struct SerialHardware *ctx), int parity)
194 {
195         UCSR0C |= (parity) << UPM0;
196 }
197
198 static void uart1_setparity(UNUSED(struct SerialHardware *ctx), int parity)
199 {
200         UCSR1C |= (parity) << UPM0;
201 }
202
203 #endif /* !__AVR_ATmega103__ */
204
205
206 static void spi_init(struct SerialHardware *_hw, struct Serial *ser)
207 {
208         struct AvrSerial *hw = (struct AvrSerial *)_hw;
209         hw->serial = ser;
210
211         /* MOSI and SCK out, MISO in */
212         SPI_DDR |= BV(SPI_MOSI_BIT) | BV(SPI_SCK_BIT);
213         SPI_DDR &= ~BV(SPI_MISO_BIT);
214         /* Enable SPI, IRQ on, Master, CPU_CLOCK/16 */
215         SPCR = BV(SPE) | BV(SPIE) | BV(MSTR) | BV(SPR0);
216 }
217
218 static void spi_cleanup(UNUSED(struct SerialHardware *ctx))
219 {
220         SPCR = 0;
221         /* Set all pins as inputs */
222         SPI_DDR &= ~(BV(SPI_MISO_BIT) | BV(SPI_MOSI_BIT) | BV(SPI_SCK_BIT));
223 }
224
225
226
227 #if defined(CONFIG_SER_HW_HANDSHAKE)
228
229 //! This interrupt is triggered when the CTS line goes high
230 SIGNAL(SIG_CTS)
231 {
232         // Re-enable UDR empty interrupt and TX, then disable CTS interrupt
233         UCR = BV(RXCIE) | BV(UDRIE) | BV(RXEN) | BV(TXEN);
234         cbi(EIMSK, EIMSKB_CTS);
235 }
236
237 #endif // CONFIG_SER_HW_HANDSHAKE
238
239
240 /*!
241  * Serial 0 TX interrupt handler
242  */
243 #ifdef __AVR_ATmega103__
244 SIGNAL(SIG_UART_DATA)
245 #else
246 SIGNAL(SIG_UART0_DATA)
247 #endif
248 {
249         if (fifo_isempty(&ser_handles[SER_UART0].txfifo))
250         {
251 #ifdef CONFIG_SER_TXFILL
252                 /*
253                  * To avoid audio interference: always transmit useless char.
254                  * Send the byte with the ninth bit cleared, the receiver in MCPM mode
255                  * will ignore it.
256                  */
257                 UCSR0B &= ~BV(TXB8);
258                 UDR0 = SER_FILL_BYTE;
259 #else
260                 /* Disable UDR empty interrupt and transmitter */
261                 UCR = BV(RXCIE) | BV(RXEN);
262 #endif
263         }
264 #if defined(CONFIG_SER_HWHANDSHAKE)
265         else if (IS_CTS_OFF)
266         {
267                 // disable rx interrupt and tx, enable CTS interrupt
268                 UCR = BV(RXCIE) | BV(RXEN);
269                 sbi(EIFR, EIMSKB_CTS);
270                 sbi(EIMSK, EIMSKB_CTS);
271         }
272 #endif // CONFIG_SER_HWHANDSHAKE
273         else
274         {
275 #ifdef CONFIG_SER_TXFILL
276                 /* Send with ninth bit set. Receiver in MCPM mode will receive it */
277                 UCSR0B |= BV(TXB8);
278 #endif
279                 UDR = fifo_pop(&ser_handles[SER_UART0].txfifo);
280         }
281 }
282
283 /*!
284  * Serial 1 TX interrupt handler
285  */
286 #ifndef __AVR_ATmega103__
287 SIGNAL(SIG_UART1_DATA)
288 {
289         if (fifo_isempty(&ser_handles[SER_UART1].txfifo))
290         {
291                 /* Disable UDR empty interrupt and transmitter */
292                 UCSR1B = BV(RXCIE) | BV(RXEN);
293         }
294 #if defined(CONFIG_SER_HWHANDSHAKE)
295         else if (IS_CTS_OFF)
296         {
297                 // disable rx interrupt and tx, enable CTS interrupt
298                 UCSR1B = BV(RXCIE) | BV(RXEN);
299                 sbi(EIFR, EIMSKB_CTS);
300                 sbi(EIMSK, EIMSKB_CTS);
301         }
302 #endif // CONFIG_SER_HWHANDSHAKE
303         else
304                 UDR1 = fifo_pop(&ser_handles[SER_UART1].txfifo);
305 }
306 #endif /* !__AVR_ATmega103__ */
307
308
309 /*!
310  * Serial 0 RX complete interrupt handler
311  */
312 #ifdef __AVR_ATmega103__
313 SIGNAL(SIG_UART_RECV)
314 #else
315 SIGNAL(SIG_UART0_RECV)
316 #endif
317 {
318         /* Should be read before UDR */
319         ser_handles[SER_UART0].status |= USR & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
320
321         /* To clear the RXC flag we must _always_ read the UDR even when we're
322          * not going to accept the incoming data, otherwise a new interrupt
323          * will occur once the handler terminates.
324          */
325         char c = UDR;
326
327         if (fifo_isfull(&ser_handles[SER_UART0].rxfifo))
328                 ser_handles[SER_UART0].status |= SERRF_RXFIFOOVERRUN;
329         else
330         {
331                 fifo_push(&ser_handles[SER_UART0].rxfifo, c);
332 #if defined(CONFIG_SER_HW_HANDSHAKE)
333                 if (fifo_isfull(&ser_handles[SER_UART0].rxfifo))
334                         RTS_OFF;
335 #endif
336         }
337 }
338
339 /*!
340  * Serial 1 RX complete interrupt handler
341  */
342 #ifndef __AVR_ATmega103__
343 SIGNAL(SIG_UART1_RECV)
344 {
345         /* Should be read before UDR */
346         ser_handles[SER_UART1].status |= UCSR1A & (SERRF_RXSROVERRUN | SERRF_FRAMEERROR);
347
348         /* To avoid an IRQ storm, we must _always_ read the UDR even when we're
349          * not going to accept the incoming data
350          */
351         char c = UDR1;
352
353         if (fifo_isfull(&ser_handles[SER_UART1].rxfifo))
354                 ser_handles[SER_UART1].status |= SERRF_RXFIFOOVERRUN;
355         else
356         {
357                 fifo_push(&ser_handles[SER_UART1].rxfifo, c);
358 #if defined(CONFIG_SER_HW_HANDSHAKE)
359                 if (fifo_isfull(&ser_handles[SER_UART1].rxfifo))
360                         RTS_OFF;
361 #endif
362         }
363 }
364 #endif /* !__AVR_ATmega103__ */
365
366
367 /*
368  * SPI Flag: true if we are transmitting/receiving with the SPI.
369  *
370  * This kludge is necessary because the SPI sends and receives bytes
371  * at the same time and the SPI IRQ is unique for send/receive.
372  * The only way to start transmission is to write data in SPDR (this
373  * is done by ser_spi_starttx()). We do this *only* if a transfer is
374  * not already started.
375  */
376 static volatile bool spi_sending = false;
377
378 static void spi_starttx(UNUSED(struct SerialHardware *ctx))
379 {
380         cpuflags_t flags;
381
382         DISABLE_IRQSAVE(flags);
383
384         /* Send data only if the SPI is not already transmitting */
385         if (!spi_sending && !fifo_isempty(&ser_handles[SER_SPI].txfifo))
386         {
387                 SPDR = fifo_pop(&ser_handles[SER_SPI].txfifo); 
388                 spi_sending = true;
389         }
390
391         ENABLE_IRQRESTORE(flags);
392 }
393
394 /*!
395  * SPI interrupt handler
396  */
397 SIGNAL(SIG_SPI)
398 {
399         /* Read incoming byte. */
400         if (!fifo_isfull(&ser_handles[SER_SPI].rxfifo))
401                 fifo_push(&ser_handles[SER_SPI].rxfifo, SPDR);
402         /*
403          * FIXME
404         else
405                 ser_handles[SER_SPI].status |= SERRF_RXFIFOOVERRUN;
406         */
407
408         /* Send */
409         if (!fifo_isempty(&ser_handles[SER_SPI].txfifo))
410                 SPDR = fifo_pop(&ser_handles[SER_SPI].txfifo);
411         else
412                 spi_sending = false;
413 }
414
415
416 /*
417
418 #pragma vector = UART_TXC_vect
419 __interrupt void UART_TXC_interrupt(void)
420 {
421   UCSRB &= ~TXCIE;
422   ReceiveMode();
423   UCSRB = RXCIE | RXEN | TXEN;  //Abilito l'Interrupt in ricezione e RX e TX  
424 }
425 */
426
427
428 static const struct SerialHardwareVT UART0_VT = 
429 {
430         .init = uart0_init,
431         .cleanup = uart0_cleanup,
432         .setbaudrate = uart0_setbaudrate,
433         .setparity = uart0_setparity,
434         .enabletxirq = uart0_enabletxirq,
435 };
436
437 static const struct SerialHardwareVT UART1_VT = 
438 {
439         .init = uart1_init,
440         .cleanup = uart1_cleanup,
441         .setbaudrate = uart1_setbaudrate,
442         .setparity = uart1_setparity,
443         .enabletxirq = uart1_enabletxirq,
444 };
445
446 static const struct SerialHardwareVT SPI_VT = 
447 {
448         .init = spi_init,
449         .cleanup = spi_cleanup,
450         .enabletxirq = spi_starttx,
451 };
452
453 static struct AvrSerial UARTDescs[SER_CNT] =
454 {
455         { 
456                 .hw = { .table = &UART0_VT }, 
457         },
458         
459         { 
460                 .hw = { .table = &UART1_VT }, 
461         },  
462
463         { 
464                 .hw = { .table = &SPI_VT }, 
465         },  
466 };
467
468 struct SerialHardware* ser_hw_getdesc(int unit)
469 {
470         ASSERT(unit < SER_CNT);
471         return &UARTDescs[unit].hw;
472 }