Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
[fw/altos] / src / avr / ao_i2c_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 TWI master mode (I2C)
23  */
24
25 uint8_t ao_i2c_mutex;
26
27 /* Send bytes over I2C.
28  *
29  * This just polls; the I2C is set to go as fast as possible,
30  * so using interrupts would take way too long
31  */
32 void
33 ao_i2c_send(void *block, uint16_t len) 
34 {
35         uint8_t *d = block;
36
37         ao_mutex_get(&ao_i2c_mutex);
38         while (len--) {
39                 while (!(UCSR1A & (1 << UDRE1)));
40                 UDR1 = *d++;
41                 while (!(UCSR1A & (1 << RXC1)));
42                 (void) UDR1;
43         }
44         ao_mutex_put(&ao_i2c_mutex);
45 }
46
47 /* Receive bytes over I2C.
48  *
49  * This sets up tow DMA engines, one reading the data and another
50  * writing constant values to the I2C transmitter as that is what
51  * clocks the data coming in.
52  */
53 void
54 ao_i2c_recv(void *block, uint16_t len) 
55 {
56         uint8_t *d = block;
57
58         ao_mutex_get(&ao_i2c_mutex);
59         while (len--) {
60                 while (!(UCSR1A & (1 << UDRE1)));
61                 UDR1 = 0;
62                 while (!(UCSR1A & (1 << RXC1)));
63                 *d++ = UDR1;
64         }
65         ao_mutex_put(&ao_i2c_mutex);
66 }
67
68 #define XCK1_DDR        DDRD
69 #define XCK1_PORT       PORTD
70 #define XCK1            PORTD5
71 #define XMS1_DDR        DDRE
72 #define XMS1_PORT       PORTE
73 #define XMS1            PORTE6
74
75 void
76 ao_i2c_init(void)
77 {
78         /* Ensure the TWI is powered */
79
80         /*
81          * Set pin directions
82          */
83         XCK1_DDR |= (1 << XCK1);
84
85         /* Clear chip select (which is negated) */
86         XMS1_PORT |= (1 < XMS1);
87         XMS1_DDR |= (1 << XMS1);
88
89         /* Set baud register to zero (required before turning transmitter on) */
90         UBRR1 = 0;
91
92         UCSR1C = ((0x3 << UMSEL10) |    /* Master I2C mode */
93                   (0 << UCSZ10) |       /* I2C mode 0 */
94                   (0 << UCPOL1));       /* I2C mode 0 */
95
96         /* Enable transmitter and receiver */
97         UCSR1B = ((1 << RXEN1) |
98                   (1 << TXEN1));
99
100         /* It says that 0 is a legal value; we'll see... */
101         UBRR1 = 0;
102 }