]> git.donarmstrong.com Git - tmk_firmware.git/blob - keyboard/ergodox/twimaster.c
Switch TWI library to use 400kHz
[tmk_firmware.git] / keyboard / ergodox / twimaster.c
1 /*************************************************************************
2 * Title:    I2C master library using hardware TWI interface
3 * Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
4 * File:     $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
5 * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
6 * Target:   any AVR device with hardware TWI 
7 * Usage:    API compatible with I2C Software Library i2cmaster.h
8 **************************************************************************/
9 #include <inttypes.h>
10 #include <compat/twi.h>
11
12 #include <i2cmaster.h>
13
14
15 /* define CPU frequency in Mhz here if not defined in Makefile */
16 #ifndef F_CPU
17 #define F_CPU 16000000UL
18 #endif
19
20 /* I2C clock in Hz */
21 #define SCL_CLOCK  400000L
22
23
24 /*************************************************************************
25  Initialization of the I2C bus interface. Need to be called only once
26 *************************************************************************/
27 void i2c_init(void)
28 {
29   /* initialize TWI clock: 400 kHz clock, TWPS = 0 => prescaler = 1 */
30   
31   TWSR = 0;                         /* no prescaler */
32   TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */
33
34 }/* i2c_init */
35
36
37 /*************************************************************************      
38   Issues a start condition and sends address and transfer direction.
39   return 0 = device accessible, 1= failed to access device
40 *************************************************************************/
41 unsigned char i2c_start(unsigned char address)
42 {
43     uint8_t   twst;
44
45         // send START condition
46         TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
47
48         // wait until transmission completed
49         while(!(TWCR & (1<<TWINT)));
50
51         // check value of TWI Status Register. Mask prescaler bits.
52         twst = TW_STATUS & 0xF8;
53         if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
54
55         // send device address
56         TWDR = address;
57         TWCR = (1<<TWINT) | (1<<TWEN);
58
59         // wail until transmission completed and ACK/NACK has been received
60         while(!(TWCR & (1<<TWINT)));
61
62         // check value of TWI Status Register. Mask prescaler bits.
63         twst = TW_STATUS & 0xF8;
64         if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
65
66         return 0;
67
68 }/* i2c_start */
69
70
71 /*************************************************************************
72  Issues a start condition and sends address and transfer direction.
73  If device is busy, use ack polling to wait until device is ready
74  
75  Input:   address and transfer direction of I2C device
76 *************************************************************************/
77 void i2c_start_wait(unsigned char address)
78 {
79     uint8_t   twst;
80
81
82     while ( 1 )
83     {
84             // send START condition
85             TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
86     
87         // wait until transmission completed
88         while(!(TWCR & (1<<TWINT)));
89     
90         // check value of TWI Status Register. Mask prescaler bits.
91         twst = TW_STATUS & 0xF8;
92         if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
93     
94         // send device address
95         TWDR = address;
96         TWCR = (1<<TWINT) | (1<<TWEN);
97     
98         // wail until transmission completed
99         while(!(TWCR & (1<<TWINT)));
100     
101         // check value of TWI Status Register. Mask prescaler bits.
102         twst = TW_STATUS & 0xF8;
103         if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) ) 
104         {           
105             /* device busy, send stop condition to terminate write operation */
106                 TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
107                 
108                 // wait until stop condition is executed and bus released
109                 while(TWCR & (1<<TWSTO));
110                 
111             continue;
112         }
113         //if( twst != TW_MT_SLA_ACK) return 1;
114         break;
115      }
116
117 }/* i2c_start_wait */
118
119
120 /*************************************************************************
121  Issues a repeated start condition and sends address and transfer direction 
122
123  Input:   address and transfer direction of I2C device
124  
125  Return:  0 device accessible
126           1 failed to access device
127 *************************************************************************/
128 unsigned char i2c_rep_start(unsigned char address)
129 {
130     return i2c_start( address );
131
132 }/* i2c_rep_start */
133
134
135 /*************************************************************************
136  Terminates the data transfer and releases the I2C bus
137 *************************************************************************/
138 void i2c_stop(void)
139 {
140     /* send stop condition */
141         TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
142         
143         // wait until stop condition is executed and bus released
144         while(TWCR & (1<<TWSTO));
145
146 }/* i2c_stop */
147
148
149 /*************************************************************************
150   Send one byte to I2C device
151   
152   Input:    byte to be transfered
153   Return:   0 write successful 
154             1 write failed
155 *************************************************************************/
156 unsigned char i2c_write( unsigned char data )
157 {       
158     uint8_t   twst;
159     
160         // send data to the previously addressed device
161         TWDR = data;
162         TWCR = (1<<TWINT) | (1<<TWEN);
163
164         // wait until transmission completed
165         while(!(TWCR & (1<<TWINT)));
166
167         // check value of TWI Status Register. Mask prescaler bits
168         twst = TW_STATUS & 0xF8;
169         if( twst != TW_MT_DATA_ACK) return 1;
170         return 0;
171
172 }/* i2c_write */
173
174
175 /*************************************************************************
176  Read one byte from the I2C device, request more data from device 
177  
178  Return:  byte read from I2C device
179 *************************************************************************/
180 unsigned char i2c_readAck(void)
181 {
182         TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
183         while(!(TWCR & (1<<TWINT)));    
184
185     return TWDR;
186
187 }/* i2c_readAck */
188
189
190 /*************************************************************************
191  Read one byte from the I2C device, read is followed by a stop condition 
192  
193  Return:  byte read from I2C device
194 *************************************************************************/
195 unsigned char i2c_readNak(void)
196 {
197         TWCR = (1<<TWINT) | (1<<TWEN);
198         while(!(TWCR & (1<<TWINT)));
199         
200     return TWDR;
201
202 }/* i2c_readNak */