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