<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>Procyon AVRlib: i2c.c Source File</title>
<link href="dox.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.4.2 -->
<div class="qindex"><a class="qindex" href="main.html">Main Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="annotated.html">Data Structures</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="functions.html">Data Fields</a> | <a class="qindex" href="globals.html">Globals</a> | <a class="qindex" href="pages.html">Related Pages</a></div>
<h1>i2c.c</h1><a href="i2c_8c.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment">00001 <span class="comment">/*! \file i2c.c \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */</span>
00002 <span class="comment">//*****************************************************************************</span>
00003 <span class="comment">//</span>
00004 <span class="comment">// File Name : 'i2c.c'</span>
00005 <span class="comment">// Title : I2C interface using AVR Two-Wire Interface (TWI) hardware</span>
00006 <span class="comment">// Author : Pascal Stang - Copyright (C) 2002-2003</span>
00007 <span class="comment">// Created : 2002.06.25</span>
00008 <span class="comment">// Revised : 2003.03.02</span>
00009 <span class="comment">// Version : 0.9</span>
00010 <span class="comment">// Target MCU : Atmel AVR series</span>
00011 <span class="comment">// Editor Tabs : 4</span>
00012 <span class="comment">//</span>
00013 <span class="comment">// This code is distributed under the GNU Public License</span>
00014 <span class="comment">// which can be found at http://www.gnu.org/licenses/gpl.txt</span>
00015 <span class="comment">//</span>
00016 <span class="comment">//*****************************************************************************</span>
00017
00018 <span class="preprocessor">#include <avr/io.h></span>
00019 <span class="preprocessor">#include <avr/interrupt.h></span>
00020
00021 <span class="preprocessor">#include "<a class="code" href="i2c_8h.html">i2c.h</a>"</span>
00022
00023 <span class="preprocessor">#include "<a class="code" href="rprintf_8h.html">rprintf.h</a>"</span> <span class="comment">// include printf function library</span>
00024 <span class="preprocessor">#include "<a class="code" href="uart2_8h.html">uart2.h</a>"</span>
00025
00026 <span class="comment">// Standard I2C bit rates are:</span>
00027 <span class="comment">// 100KHz for slow speed</span>
00028 <span class="comment">// 400KHz for high speed</span>
00029
00030 <span class="comment">//#define I2C_DEBUG</span>
00031
00032 <span class="comment">// I2C state and address variables</span>
00033 <span class="keyword">static</span> <span class="keyword">volatile</span> eI2cStateType I2cState;
00034 <span class="keyword">static</span> u08 I2cDeviceAddrRW;
00035 <span class="comment">// send/transmit buffer (outgoing data)</span>
00036 <span class="keyword">static</span> u08 I2cSendData[I2C_SEND_DATA_BUFFER_SIZE];
00037 <span class="keyword">static</span> u08 I2cSendDataIndex;
00038 <span class="keyword">static</span> u08 I2cSendDataLength;
00039 <span class="comment">// receive buffer (incoming data)</span>
00040 <span class="keyword">static</span> u08 I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE];
00041 <span class="keyword">static</span> u08 I2cReceiveDataIndex;
00042 <span class="keyword">static</span> u08 I2cReceiveDataLength;
00043
00044 <span class="comment">// function pointer to i2c receive routine</span><span class="comment"></span>
00045 <span class="comment">//! I2cSlaveReceive is called when this processor</span>
00046 <span class="comment"></span><span class="comment">// is addressed as a slave for writing</span>
00047 <span class="keyword">static</span> void (*i2cSlaveReceive)(u08 receiveDataLength, u08* recieveData);<span class="comment"></span>
00048 <span class="comment">//! I2cSlaveTransmit is called when this processor</span>
00049 <span class="comment"></span><span class="comment">// is addressed as a slave for reading</span>
00050 <span class="keyword">static</span> u08 (*i2cSlaveTransmit)(u08 transmitDataLengthMax, u08* transmitData);
00051
00052 <span class="comment">// functions</span>
<a name="l00053"></a><a class="code" href="i2csw_8h.html#a1">00053</a> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a10">i2cInit</a>(<span class="keywordtype">void</span>)
00054 {
00055 <span class="comment">// set pull-up resistors on I2C bus pins</span>
00056 <span class="comment">// TODO: should #ifdef these</span>
00057 sbi(PORTC, 0); <span class="comment">// i2c SCL on ATmega163,323,16,32,etc</span>
00058 sbi(PORTC, 1); <span class="comment">// i2c SDA on ATmega163,323,16,32,etc</span>
00059 sbi(PORTD, 0); <span class="comment">// i2c SCL on ATmega128,64</span>
00060 sbi(PORTD, 1); <span class="comment">// i2c SDA on ATmega128,64</span>
00061
00062 <span class="comment">// clear SlaveReceive and SlaveTransmit handler to null</span>
00063 i2cSlaveReceive = 0;
00064 i2cSlaveTransmit = 0;
00065 <span class="comment">// set i2c bit rate to 100KHz</span>
00066 <a class="code" href="i2c_8c.html#a11">i2cSetBitrate</a>(100);
00067 <span class="comment">// enable TWI (two-wire interface)</span>
00068 sbi(TWCR, TWEN);
00069 <span class="comment">// set state</span>
00070 I2cState = I2C_IDLE;
00071 <span class="comment">// enable TWI interrupt and slave address ACK</span>
00072 sbi(TWCR, TWIE);
00073 sbi(TWCR, TWEA);
00074 <span class="comment">//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));</span>
00075 <span class="comment">// enable interrupts</span>
00076 sei();
00077 }
00078
<a name="l00079"></a><a class="code" href="i2c_8h.html#a39">00079</a> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a11">i2cSetBitrate</a>(u16 bitrateKHz)
00080 {
00081 u08 bitrate_div;
00082 <span class="comment">// set i2c bitrate</span>
00083 <span class="comment">// SCL freq = F_CPU/(16+2*TWBR))</span>
00084 <span class="preprocessor"> #ifdef TWPS0</span>
00085 <span class="preprocessor"></span> <span class="comment">// for processors with additional bitrate division (mega128)</span>
00086 <span class="comment">// SCL freq = F_CPU/(16+2*TWBR*4^TWPS)</span>
00087 <span class="comment">// set TWPS to zero</span>
00088 cbi(TWSR, TWPS0);
00089 cbi(TWSR, TWPS1);
00090 <span class="preprocessor"> #endif</span>
00091 <span class="preprocessor"></span> <span class="comment">// calculate bitrate division </span>
00092 bitrate_div = ((F_CPU/1000l)/bitrateKHz);
00093 <span class="keywordflow">if</span>(bitrate_div >= 16)
00094 bitrate_div = (bitrate_div-16)/2;
00095 outb(TWBR, bitrate_div);
00096 }
00097
<a name="l00098"></a><a class="code" href="i2c_8h.html#a40">00098</a> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a12">i2cSetLocalDeviceAddr</a>(u08 deviceAddr, u08 genCallEn)
00099 {
00100 <span class="comment">// set local device address (used in slave mode only)</span>
00101 outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) );
00102 }
00103
<a name="l00104"></a><a class="code" href="i2c_8h.html#a41">00104</a> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a13">i2cSetSlaveReceiveHandler</a>(<span class="keywordtype">void</span> (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData))
00105 {
00106 i2cSlaveReceive = i2cSlaveRx_func;
00107 }
00108
<a name="l00109"></a><a class="code" href="i2c_8h.html#a42">00109</a> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a14">i2cSetSlaveTransmitHandler</a>(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData))
00110 {
00111 i2cSlaveTransmit = i2cSlaveTx_func;
00112 }
00113
<a name="l00114"></a><a class="code" href="i2c_8h.html#a43">00114</a> <span class="keyword">inline</span> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a15">i2cSendStart</a>(<span class="keywordtype">void</span>)
00115 {
00116 <span class="comment">// send start condition</span>
00117 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));
00118 }
00119
<a name="l00120"></a><a class="code" href="i2c_8h.html#a44">00120</a> <span class="keyword">inline</span> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a16">i2cSendStop</a>(<span class="keywordtype">void</span>)
00121 {
00122 <span class="comment">// transmit stop condition</span>
00123 <span class="comment">// leave with TWEA on for slave receiving</span>
00124 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));
00125 }
00126
<a name="l00127"></a><a class="code" href="i2c_8h.html#a45">00127</a> <span class="keyword">inline</span> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a17">i2cWaitForComplete</a>(<span class="keywordtype">void</span>)
00128 {
00129 <span class="comment">// wait for i2c interface to complete operation</span>
00130 <span class="keywordflow">while</span>( !(inb(TWCR) & BV(TWINT)) );
00131 }
00132
<a name="l00133"></a><a class="code" href="i2c_8h.html#a46">00133</a> <span class="keyword">inline</span> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a18">i2cSendByte</a>(u08 data)
00134 {
00135 <span class="comment">// save data to the TWDR</span>
00136 outb(TWDR, data);
00137 <span class="comment">// begin send</span>
00138 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
00139 }
00140
<a name="l00141"></a><a class="code" href="i2c_8h.html#a47">00141</a> <span class="keyword">inline</span> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a19">i2cReceiveByte</a>(u08 ackFlag)
00142 {
00143 <span class="comment">// begin receive over i2c</span>
00144 <span class="keywordflow">if</span>( ackFlag )
00145 {
00146 <span class="comment">// ackFlag = TRUE: ACK the recevied data</span>
00147 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
00148 }
00149 <span class="keywordflow">else</span>
00150 {
00151 <span class="comment">// ackFlag = FALSE: NACK the recevied data</span>
00152 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
00153 }
00154 }
00155
<a name="l00156"></a><a class="code" href="i2c_8h.html#a48">00156</a> <span class="keyword">inline</span> u08 <a class="code" href="i2c_8c.html#a20">i2cGetReceivedByte</a>(<span class="keywordtype">void</span>)
00157 {
00158 <span class="comment">// retieve received data byte from i2c TWDR</span>
00159 <span class="keywordflow">return</span>( inb(TWDR) );
00160 }
00161
<a name="l00162"></a><a class="code" href="i2c_8h.html#a49">00162</a> <span class="keyword">inline</span> u08 <a class="code" href="i2c_8c.html#a21">i2cGetStatus</a>(<span class="keywordtype">void</span>)
00163 {
00164 <span class="comment">// retieve current i2c status from i2c TWSR</span>
00165 <span class="keywordflow">return</span>( inb(TWSR) );
00166 }
00167
<a name="l00168"></a><a class="code" href="i2c_8h.html#a50">00168</a> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a22">i2cMasterSend</a>(u08 deviceAddr, u08 length, u08* data)
00169 {
00170 u08 i;
00171 <span class="comment">// wait for interface to be ready</span>
00172 <span class="keywordflow">while</span>(I2cState);
00173 <span class="comment">// set state</span>
00174 I2cState = I2C_MASTER_TX;
00175 <span class="comment">// save data</span>
00176 I2cDeviceAddrRW = (deviceAddr & 0xFE); <span class="comment">// RW cleared: write operation</span>
00177 <span class="keywordflow">for</span>(i=0; i<length; i++)
00178 I2cSendData[i] = *data++;
00179 I2cSendDataIndex = 0;
00180 I2cSendDataLength = length;
00181 <span class="comment">// send start condition</span>
00182 <a class="code" href="i2c_8c.html#a15">i2cSendStart</a>();
00183 }
00184
<a name="l00185"></a><a class="code" href="i2c_8h.html#a51">00185</a> <span class="keywordtype">void</span> <a class="code" href="i2c_8c.html#a23">i2cMasterReceive</a>(u08 deviceAddr, u08 length, u08* data)
00186 {
00187 u08 i;
00188 <span class="comment">// wait for interface to be ready</span>
00189 <span class="keywordflow">while</span>(I2cState);
00190 <span class="comment">// set state</span>
00191 I2cState = I2C_MASTER_RX;
00192 <span class="comment">// save data</span>
00193 I2cDeviceAddrRW = (deviceAddr|0x01); <span class="comment">// RW set: read operation</span>
00194 I2cReceiveDataIndex = 0;
00195 I2cReceiveDataLength = length;
00196 <span class="comment">// send start condition</span>
00197 <a class="code" href="i2c_8c.html#a15">i2cSendStart</a>();
00198 <span class="comment">// wait for data</span>
00199 <span class="keywordflow">while</span>(I2cState);
00200 <span class="comment">// return data</span>
00201 <span class="keywordflow">for</span>(i=0; i<length; i++)
00202 *data++ = I2cReceiveData[i];
00203 }
00204
<a name="l00205"></a><a class="code" href="i2c_8h.html#a52">00205</a> u08 <a class="code" href="i2c_8c.html#a24">i2cMasterSendNI</a>(u08 deviceAddr, u08 length, u08* data)
00206 {
00207 u08 retval = I2C_OK;
00208
00209 <span class="comment">// disable TWI interrupt</span>
00210 cbi(TWCR, TWIE);
00211
00212 <span class="comment">// send start condition</span>
00213 <a class="code" href="i2c_8c.html#a15">i2cSendStart</a>();
00214 <a class="code" href="i2c_8c.html#a17">i2cWaitForComplete</a>();
00215
00216 <span class="comment">// send device address with write</span>
00217 <a class="code" href="i2c_8c.html#a18">i2cSendByte</a>( deviceAddr & 0xFE );
00218 <a class="code" href="i2c_8c.html#a17">i2cWaitForComplete</a>();
00219
00220 <span class="comment">// check if device is present and live</span>
00221 <span class="keywordflow">if</span>( inb(TWSR) == TW_MT_SLA_ACK)
00222 {
00223 <span class="comment">// send data</span>
00224 <span class="keywordflow">while</span>(length)
00225 {
00226 <a class="code" href="i2c_8c.html#a18">i2cSendByte</a>( *data++ );
00227 <a class="code" href="i2c_8c.html#a17">i2cWaitForComplete</a>();
00228 length--;
00229 }
00230 }
00231 <span class="keywordflow">else</span>
00232 {
00233 <span class="comment">// device did not ACK it's address,</span>
00234 <span class="comment">// data will not be transferred</span>
00235 <span class="comment">// return error</span>
00236 retval = I2C_ERROR_NODEV;
00237 }
00238
00239 <span class="comment">// transmit stop condition</span>
00240 <span class="comment">// leave with TWEA on for slave receiving</span>
00241 <a class="code" href="i2c_8c.html#a16">i2cSendStop</a>();
00242 <span class="keywordflow">while</span>( !(inb(TWCR) & BV(TWSTO)) );
00243
00244 <span class="comment">// enable TWI interrupt</span>
00245 sbi(TWCR, TWIE);
00246
00247 <span class="keywordflow">return</span> retval;
00248 }
00249
<a name="l00250"></a><a class="code" href="i2c_8h.html#a53">00250</a> u08 <a class="code" href="i2c_8c.html#a25">i2cMasterReceiveNI</a>(u08 deviceAddr, u08 length, u08 *data)
00251 {
00252 u08 retval = I2C_OK;
00253
00254 <span class="comment">// disable TWI interrupt</span>
00255 cbi(TWCR, TWIE);
00256
00257 <span class="comment">// send start condition</span>
00258 <a class="code" href="i2c_8c.html#a15">i2cSendStart</a>();
00259 <a class="code" href="i2c_8c.html#a17">i2cWaitForComplete</a>();
00260
00261 <span class="comment">// send device address with read</span>
00262 <a class="code" href="i2c_8c.html#a18">i2cSendByte</a>( deviceAddr | 0x01 );
00263 <a class="code" href="i2c_8c.html#a17">i2cWaitForComplete</a>();
00264
00265 <span class="comment">// check if device is present and live</span>
00266 <span class="keywordflow">if</span>( inb(TWSR) == TW_MR_SLA_ACK)
00267 {
00268 <span class="comment">// accept receive data and ack it</span>
00269 <span class="keywordflow">while</span>(length > 1)
00270 {
00271 <a class="code" href="i2c_8c.html#a19">i2cReceiveByte</a>(TRUE);
00272 <a class="code" href="i2c_8c.html#a17">i2cWaitForComplete</a>();
00273 *data++ = <a class="code" href="i2c_8c.html#a20">i2cGetReceivedByte</a>();
00274 <span class="comment">// decrement length</span>
00275 length--;
00276 }
00277
00278 <span class="comment">// accept receive data and nack it (last-byte signal)</span>
00279 <a class="code" href="i2c_8c.html#a19">i2cReceiveByte</a>(FALSE);
00280 <a class="code" href="i2c_8c.html#a17">i2cWaitForComplete</a>();
00281 *data++ = <a class="code" href="i2c_8c.html#a20">i2cGetReceivedByte</a>();
00282 }
00283 <span class="keywordflow">else</span>
00284 {
00285 <span class="comment">// device did not ACK it's address,</span>
00286 <span class="comment">// data will not be transferred</span>
00287 <span class="comment">// return error</span>
00288 retval = I2C_ERROR_NODEV;
00289 }
00290
00291 <span class="comment">// transmit stop condition</span>
00292 <span class="comment">// leave with TWEA on for slave receiving</span>
00293 <a class="code" href="i2c_8c.html#a16">i2cSendStop</a>();
00294
00295 <span class="comment">// enable TWI interrupt</span>
00296 sbi(TWCR, TWIE);
00297
00298 <span class="keywordflow">return</span> retval;
00299 }
00300 <span class="comment">/*</span>
00301 <span class="comment">void i2cMasterTransferNI(u08 deviceAddr, u08 sendlength, u08* senddata, u08 receivelength, u08* receivedata)</span>
00302 <span class="comment">{</span>
00303 <span class="comment"> // disable TWI interrupt</span>
00304 <span class="comment"> cbi(TWCR, TWIE);</span>
00305 <span class="comment"></span>
00306 <span class="comment"> // send start condition</span>
00307 <span class="comment"> i2cSendStart();</span>
00308 <span class="comment"> i2cWaitForComplete();</span>
00309 <span class="comment"></span>
00310 <span class="comment"> // if there's data to be sent, do it</span>
00311 <span class="comment"> if(sendlength)</span>
00312 <span class="comment"> {</span>
00313 <span class="comment"> // send device address with write</span>
00314 <span class="comment"> i2cSendByte( deviceAddr & 0xFE );</span>
00315 <span class="comment"> i2cWaitForComplete();</span>
00316 <span class="comment"> </span>
00317 <span class="comment"> // send data</span>
00318 <span class="comment"> while(sendlength)</span>
00319 <span class="comment"> {</span>
00320 <span class="comment"> i2cSendByte( *senddata++ );</span>
00321 <span class="comment"> i2cWaitForComplete();</span>
00322 <span class="comment"> sendlength--;</span>
00323 <span class="comment"> }</span>
00324 <span class="comment"> }</span>
00325 <span class="comment"></span>
00326 <span class="comment"> // if there's data to be received, do it</span>
00327 <span class="comment"> if(receivelength)</span>
00328 <span class="comment"> {</span>
00329 <span class="comment"> // send repeated start condition</span>
00330 <span class="comment"> i2cSendStart();</span>
00331 <span class="comment"> i2cWaitForComplete();</span>
00332 <span class="comment"></span>
00333 <span class="comment"> // send device address with read</span>
00334 <span class="comment"> i2cSendByte( deviceAddr | 0x01 );</span>
00335 <span class="comment"> i2cWaitForComplete();</span>
00336 <span class="comment"></span>
00337 <span class="comment"> // accept receive data and ack it</span>
00338 <span class="comment"> while(receivelength > 1)</span>
00339 <span class="comment"> {</span>
00340 <span class="comment"> i2cReceiveByte(TRUE);</span>
00341 <span class="comment"> i2cWaitForComplete();</span>
00342 <span class="comment"> *receivedata++ = i2cGetReceivedByte();</span>
00343 <span class="comment"> // decrement length</span>
00344 <span class="comment"> receivelength--;</span>
00345 <span class="comment"> }</span>
00346 <span class="comment"></span>
00347 <span class="comment"> // accept receive data and nack it (last-byte signal)</span>
00348 <span class="comment"> i2cReceiveByte(TRUE);</span>
00349 <span class="comment"> i2cWaitForComplete();</span>
00350 <span class="comment"> *receivedata++ = i2cGetReceivedByte();</span>
00351 <span class="comment"> }</span>
00352 <span class="comment"> </span>
00353 <span class="comment"> // transmit stop condition</span>
00354 <span class="comment"> // leave with TWEA on for slave receiving</span>
00355 <span class="comment"> i2cSendStop();</span>
00356 <span class="comment"> while( !(inb(TWCR) & BV(TWSTO)) );</span>
00357 <span class="comment"></span>
00358 <span class="comment"> // enable TWI interrupt</span>
00359 <span class="comment"> sbi(TWCR, TWIE);</span>
00360 <span class="comment">}</span>
00361 <span class="comment">*/</span>
00362 <span class="comment"></span>
00363 <span class="comment">//! I2C (TWI) interrupt service routine</span>
<a name="l00364"></a><a class="code" href="i2c_8c.html#a26">00364</a> <span class="comment"></span><a class="code" href="a2d_8c.html#a10">SIGNAL</a>(SIG_2WIRE_SERIAL)
00365 {
00366 <span class="comment">// read status bits</span>
00367 u08 status = inb(TWSR) & TWSR_STATUS_MASK;
00368
00369 <span class="keywordflow">switch</span>(status)
00370 {
00371 <span class="comment">// Master General</span>
00372 <span class="keywordflow">case</span> TW_START: <span class="comment">// 0x08: Sent start condition</span>
00373 <span class="keywordflow">case</span> TW_REP_START: <span class="comment">// 0x10: Sent repeated start condition</span>
00374 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00375 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00376 rprintf(<span class="stringliteral">"I2C: M->START\r\n"</span>);
00377 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00378 <span class="preprocessor"> #endif</span>
00379 <span class="preprocessor"></span> <span class="comment">// send device address</span>
00380 <a class="code" href="i2c_8c.html#a18">i2cSendByte</a>(I2cDeviceAddrRW);
00381 <span class="keywordflow">break</span>;
00382
00383 <span class="comment">// Master Transmitter & Receiver status codes</span>
00384 <span class="keywordflow">case</span> TW_MT_SLA_ACK: <span class="comment">// 0x18: Slave address acknowledged</span>
00385 <span class="keywordflow">case</span> TW_MT_DATA_ACK: <span class="comment">// 0x28: Data acknowledged</span>
00386 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00387 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00388 rprintf(<span class="stringliteral">"I2C: MT->SLA_ACK or DATA_ACK\r\n"</span>);
00389 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00390 <span class="preprocessor"> #endif</span>
00391 <span class="preprocessor"></span> <span class="keywordflow">if</span>(I2cSendDataIndex < I2cSendDataLength)
00392 {
00393 <span class="comment">// send data</span>
00394 <a class="code" href="i2c_8c.html#a18">i2cSendByte</a>( I2cSendData[I2cSendDataIndex++] );
00395 }
00396 <span class="keywordflow">else</span>
00397 {
00398 <span class="comment">// transmit stop condition, enable SLA ACK</span>
00399 <a class="code" href="i2c_8c.html#a16">i2cSendStop</a>();
00400 <span class="comment">// set state</span>
00401 I2cState = I2C_IDLE;
00402 }
00403 <span class="keywordflow">break</span>;
00404 <span class="keywordflow">case</span> TW_MR_DATA_NACK: <span class="comment">// 0x58: Data received, NACK reply issued</span>
00405 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00406 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00407 rprintf(<span class="stringliteral">"I2C: MR->DATA_NACK\r\n"</span>);
00408 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00409 <span class="preprocessor"> #endif</span>
00410 <span class="preprocessor"></span> <span class="comment">// store final received data byte</span>
00411 I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
00412 <span class="comment">// continue to transmit STOP condition</span>
00413 <span class="keywordflow">case</span> TW_MR_SLA_NACK: <span class="comment">// 0x48: Slave address not acknowledged</span>
00414 <span class="keywordflow">case</span> TW_MT_SLA_NACK: <span class="comment">// 0x20: Slave address not acknowledged</span>
00415 <span class="keywordflow">case</span> TW_MT_DATA_NACK: <span class="comment">// 0x30: Data not acknowledged</span>
00416 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00417 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00418 rprintf(<span class="stringliteral">"I2C: MTR->SLA_NACK or MT->DATA_NACK\r\n"</span>);
00419 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00420 <span class="preprocessor"> #endif</span>
00421 <span class="preprocessor"></span> <span class="comment">// transmit stop condition, enable SLA ACK</span>
00422 <a class="code" href="i2c_8c.html#a16">i2cSendStop</a>();
00423 <span class="comment">// set state</span>
00424 I2cState = I2C_IDLE;
00425 <span class="keywordflow">break</span>;
00426 <span class="keywordflow">case</span> TW_MT_ARB_LOST: <span class="comment">// 0x38: Bus arbitration lost</span>
00427 <span class="comment">//case TW_MR_ARB_LOST: // 0x38: Bus arbitration lost</span>
00428 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00429 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00430 rprintf(<span class="stringliteral">"I2C: MT->ARB_LOST\r\n"</span>);
00431 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00432 <span class="preprocessor"> #endif</span>
00433 <span class="preprocessor"></span> <span class="comment">// release bus</span>
00434 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
00435 <span class="comment">// set state</span>
00436 I2cState = I2C_IDLE;
00437 <span class="comment">// release bus and transmit start when bus is free</span>
00438 <span class="comment">//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));</span>
00439 <span class="keywordflow">break</span>;
00440 <span class="keywordflow">case</span> TW_MR_DATA_ACK: <span class="comment">// 0x50: Data acknowledged</span>
00441 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00442 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00443 rprintf(<span class="stringliteral">"I2C: MR->DATA_ACK\r\n"</span>);
00444 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00445 <span class="preprocessor"> #endif</span>
00446 <span class="preprocessor"></span> <span class="comment">// store received data byte</span>
00447 I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
00448 <span class="comment">// fall-through to see if more bytes will be received</span>
00449 <span class="keywordflow">case</span> TW_MR_SLA_ACK: <span class="comment">// 0x40: Slave address acknowledged</span>
00450 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00451 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00452 rprintf(<span class="stringliteral">"I2C: MR->SLA_ACK\r\n"</span>);
00453 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00454 <span class="preprocessor"> #endif</span>
00455 <span class="preprocessor"></span> <span class="keywordflow">if</span>(I2cReceiveDataIndex < (I2cReceiveDataLength-1))
00456 <span class="comment">// data byte will be received, reply with ACK (more bytes in transfer)</span>
00457 <a class="code" href="i2c_8c.html#a19">i2cReceiveByte</a>(TRUE);
00458 <span class="keywordflow">else</span>
00459 <span class="comment">// data byte will be received, reply with NACK (final byte in transfer)</span>
00460 <a class="code" href="i2c_8c.html#a19">i2cReceiveByte</a>(FALSE);
00461 <span class="keywordflow">break</span>;
00462
00463 <span class="comment">// Slave Receiver status codes</span>
00464 <span class="keywordflow">case</span> TW_SR_SLA_ACK: <span class="comment">// 0x60: own SLA+W has been received, ACK has been returned</span>
00465 <span class="keywordflow">case</span> TW_SR_ARB_LOST_SLA_ACK: <span class="comment">// 0x68: own SLA+W has been received, ACK has been returned</span>
00466 <span class="keywordflow">case</span> TW_SR_GCALL_ACK: <span class="comment">// 0x70: GCA+W has been received, ACK has been returned</span>
00467 <span class="keywordflow">case</span> TW_SR_ARB_LOST_GCALL_ACK: <span class="comment">// 0x78: GCA+W has been received, ACK has been returned</span>
00468 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00469 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00470 rprintf(<span class="stringliteral">"I2C: SR->SLA_ACK\r\n"</span>);
00471 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00472 <span class="preprocessor"> #endif</span>
00473 <span class="preprocessor"></span> <span class="comment">// we are being addressed as slave for writing (data will be received from master)</span>
00474 <span class="comment">// set state</span>
00475 I2cState = I2C_SLAVE_RX;
00476 <span class="comment">// prepare buffer</span>
00477 I2cReceiveDataIndex = 0;
00478 <span class="comment">// receive data byte and return ACK</span>
00479 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
00480 <span class="keywordflow">break</span>;
00481 <span class="keywordflow">case</span> TW_SR_DATA_ACK: <span class="comment">// 0x80: data byte has been received, ACK has been returned</span>
00482 <span class="keywordflow">case</span> TW_SR_GCALL_DATA_ACK: <span class="comment">// 0x90: data byte has been received, ACK has been returned</span>
00483 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00484 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00485 rprintf(<span class="stringliteral">"I2C: SR->DATA_ACK\r\n"</span>);
00486 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00487 <span class="preprocessor"> #endif</span>
00488 <span class="preprocessor"></span> <span class="comment">// get previously received data byte</span>
00489 I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
00490 <span class="comment">// check receive buffer status</span>
00491 <span class="keywordflow">if</span>(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE)
00492 {
00493 <span class="comment">// receive data byte and return ACK</span>
00494 <a class="code" href="i2c_8c.html#a19">i2cReceiveByte</a>(TRUE);
00495 <span class="comment">//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));</span>
00496 }
00497 <span class="keywordflow">else</span>
00498 {
00499 <span class="comment">// receive data byte and return NACK</span>
00500 <a class="code" href="i2c_8c.html#a19">i2cReceiveByte</a>(FALSE);
00501 <span class="comment">//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));</span>
00502 }
00503 <span class="keywordflow">break</span>;
00504 <span class="keywordflow">case</span> TW_SR_DATA_NACK: <span class="comment">// 0x88: data byte has been received, NACK has been returned</span>
00505 <span class="keywordflow">case</span> TW_SR_GCALL_DATA_NACK: <span class="comment">// 0x98: data byte has been received, NACK has been returned</span>
00506 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00507 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00508 rprintf(<span class="stringliteral">"I2C: SR->DATA_NACK\r\n"</span>);
00509 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00510 <span class="preprocessor"> #endif</span>
00511 <span class="preprocessor"></span> <span class="comment">// receive data byte and return NACK</span>
00512 <a class="code" href="i2c_8c.html#a19">i2cReceiveByte</a>(FALSE);
00513 <span class="comment">//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));</span>
00514 <span class="keywordflow">break</span>;
00515 <span class="keywordflow">case</span> TW_SR_STOP: <span class="comment">// 0xA0: STOP or REPEATED START has been received while addressed as slave</span>
00516 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00517 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00518 rprintf(<span class="stringliteral">"I2C: SR->SR_STOP\r\n"</span>);
00519 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00520 <span class="preprocessor"> #endif</span>
00521 <span class="preprocessor"></span> <span class="comment">// switch to SR mode with SLA ACK</span>
00522 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
00523 <span class="comment">// i2c receive is complete, call i2cSlaveReceive</span>
00524 <span class="keywordflow">if</span>(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData);
00525 <span class="comment">// set state</span>
00526 I2cState = I2C_IDLE;
00527 <span class="keywordflow">break</span>;
00528
00529 <span class="comment">// Slave Transmitter</span>
00530 <span class="keywordflow">case</span> TW_ST_SLA_ACK: <span class="comment">// 0xA8: own SLA+R has been received, ACK has been returned</span>
00531 <span class="keywordflow">case</span> TW_ST_ARB_LOST_SLA_ACK: <span class="comment">// 0xB0: GCA+R has been received, ACK has been returned</span>
00532 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00533 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00534 rprintf(<span class="stringliteral">"I2C: ST->SLA_ACK\r\n"</span>);
00535 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00536 <span class="preprocessor"> #endif</span>
00537 <span class="preprocessor"></span> <span class="comment">// we are being addressed as slave for reading (data must be transmitted back to master)</span>
00538 <span class="comment">// set state</span>
00539 I2cState = I2C_SLAVE_TX;
00540 <span class="comment">// request data from application</span>
00541 <span class="keywordflow">if</span>(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData);
00542 <span class="comment">// reset data index</span>
00543 I2cSendDataIndex = 0;
00544 <span class="comment">// fall-through to transmit first data byte</span>
00545 <span class="keywordflow">case</span> TW_ST_DATA_ACK: <span class="comment">// 0xB8: data byte has been transmitted, ACK has been received</span>
00546 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00547 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00548 rprintf(<span class="stringliteral">"I2C: ST->DATA_ACK\r\n"</span>);
00549 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00550 <span class="preprocessor"> #endif</span>
00551 <span class="preprocessor"></span> <span class="comment">// transmit data byte</span>
00552 outb(TWDR, I2cSendData[I2cSendDataIndex++]);
00553 <span class="keywordflow">if</span>(I2cSendDataIndex < I2cSendDataLength)
00554 <span class="comment">// expect ACK to data byte</span>
00555 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
00556 <span class="keywordflow">else</span>
00557 <span class="comment">// expect NACK to data byte</span>
00558 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
00559 <span class="keywordflow">break</span>;
00560 <span class="keywordflow">case</span> TW_ST_DATA_NACK: <span class="comment">// 0xC0: data byte has been transmitted, NACK has been received</span>
00561 <span class="keywordflow">case</span> TW_ST_LAST_DATA: <span class="comment">// 0xC8:</span>
00562 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00563 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00564 rprintf(<span class="stringliteral">"I2C: ST->DATA_NACK or LAST_DATA\r\n"</span>);
00565 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00566 <span class="preprocessor"> #endif</span>
00567 <span class="preprocessor"></span> <span class="comment">// all done</span>
00568 <span class="comment">// switch to open slave</span>
00569 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
00570 <span class="comment">// set state</span>
00571 I2cState = I2C_IDLE;
00572 <span class="keywordflow">break</span>;
00573
00574 <span class="comment">// Misc</span>
00575 <span class="keywordflow">case</span> TW_NO_INFO: <span class="comment">// 0xF8: No relevant state information</span>
00576 <span class="comment">// do nothing</span>
00577 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00578 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00579 rprintf(<span class="stringliteral">"I2C: NO_INFO\r\n"</span>);
00580 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00581 <span class="preprocessor"> #endif</span>
00582 <span class="preprocessor"></span> <span class="keywordflow">break</span>;
00583 <span class="keywordflow">case</span> TW_BUS_ERROR: <span class="comment">// 0x00: Bus error due to illegal start or stop condition</span>
00584 <span class="preprocessor"> #ifdef I2C_DEBUG</span>
00585 <span class="preprocessor"></span> <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1AddToTxBuffer);
00586 rprintf(<span class="stringliteral">"I2C: BUS_ERROR\r\n"</span>);
00587 <a class="code" href="group__rprintf.html#ga0">rprintfInit</a>(uart1SendByte);
00588 <span class="preprocessor"> #endif</span>
00589 <span class="preprocessor"></span> <span class="comment">// reset internal hardware and release bus</span>
00590 outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));
00591 <span class="comment">// set state</span>
00592 I2cState = I2C_IDLE;
00593 <span class="keywordflow">break</span>;
00594 }
00595 }
00596
<a name="l00597"></a><a class="code" href="i2c_8h.html#a54">00597</a> eI2cStateType <a class="code" href="i2c_8c.html#a27">i2cGetState</a>(<span class="keywordtype">void</span>)
00598 {
00599 <span class="keywordflow">return</span> I2cState;
00600 }
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Sun Oct 29 03:41:06 2006 for Procyon AVRlib by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.4.2 </small></address>
</body>
</html>
|