0d509cb77660dc23bd5894d6c88b8df1ffa0c1d5
[fw/altos] / src / avr / ao_spi_usart.c
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include "ao.h"
20
21 /*
22  * Atmega32u4 USART in MSPIM (master SPI mode)
23  */
24
25 __xdata uint8_t ao_spi_mutex;
26
27 /* Send bytes over SPI.
28  *
29  * This just polls; the SPI is set to go as fast as possible,
30  * so using interrupts would take way too long
31  */
32 void
33 ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant
34 {
35         uint8_t *d = block;
36
37         while (len--) {
38                 while (!(UCSR1A & (1 << UDRE1)));
39                 UDR1 = *d++;
40                 while (!(UCSR1A & (1 << RXC1)));
41                 (void) UDR1;
42         }
43 }
44
45 /* Receive bytes over SPI.
46  *
47  * Poll, sending zeros and reading data back
48  */
49 void
50 ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant
51 {
52         uint8_t *d = block;
53
54         /* Clear any pending data */
55         while (UCSR1A & (1 << RXC1))
56                 (void) UDR1;
57         
58         while (len--) {
59                 while (!(UCSR1A & (1 << UDRE1)));
60                 UDR1 = 0;
61                 while (!(UCSR1A & (1 << RXC1)));
62                 *d++ = UDR1;
63         }
64 }
65
66 /*
67  * Initialize USART0 for SPI using config alt 2
68  *
69  *      MO      P1_5
70  *      MI      P1_4
71  *      CLK     P1_3
72  *
73  * Chip select is the responsibility of the caller
74  */
75
76 #define XCK1_DDR        DDRD
77 #define XCK1_PORT       PORTD
78 #define XCK1            PORTD5
79 #define XMS1_DDR        DDRE
80 #define XMS1_PORT       PORTE
81 #define XMS1            PORTE6
82
83 void
84 ao_spi_init(void)
85 {
86         /* Ensure the USART is powered */
87         PRR1 &= ~(1 << PRUSART1);
88
89         /*
90          * Set pin directions
91          */
92         XCK1_DDR |= (1 << XCK1);
93
94         /* Clear chip select (which is negated) */
95         XMS1_PORT |= (1 < XMS1);
96         XMS1_DDR |= (1 << XMS1);
97
98         /* Set baud register to zero (required before turning transmitter on) */
99         UBRR1 = 0;
100
101         UCSR1C = ((0x3 << UMSEL10) |    /* Master SPI mode */
102                   (0 << UCSZ10) |       /* SPI mode 0 */
103                   (0 << UCPOL1));       /* SPI mode 0 */
104
105         /* Enable transmitter and receiver */
106         UCSR1B = ((1 << RXEN1) |
107                   (1 << TXEN1));
108
109         /* It says that 0 is a legal value; we'll see... */
110         UBRR1 = 0;
111 }