twi.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00023 /* ************************************************************************
00024 
00025 Copyright (c) 2006, Atmel Corporation All rights reserved.
00026 
00027 Redistribution and use in source and binary forms, with or without
00028 modification, are permitted provided that the following conditions are met:
00029 
00030 1. Redistributions of source code must retain the above copyright notice,
00031 this list of conditions and the
00032 following disclaimer.
00033 
00034 2. Redistributions in binary form must reproduce the above copyright notice,
00035 this list of conditions and the following disclaimer in the documentation
00036 and/or other materials provided with the distribution.
00037 
00038 3. The name of ATMEL may not be used to endorse or promote products
00039 derived from this software without specific prior written permission.
00040 
00041 THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS
00042 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00043 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00044 PARTICULAR PURPOSE ARE EXPRESSLY AND SPECIFICALLY
00045 DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00046 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00047 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00048 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00049 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00050 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00051 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
00052 WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00053 
00054 POSSIBILITY OF SUCH DAMAGE.
00055 
00056 ************************************************************************ */
00057 
00058 #include "twi.h"
00059 
00060 
00061 /*
00062  * twi_set_speed: -  Set the twi bus speed in cojunction with the clock frequency
00063  *
00064  * speed:       The desired twi bus speed
00065  * cpu_hz:      The current running cpu_clock frequency
00066  * returns:     none
00067  */
00068 int twi_set_speed(unsigned int speed, unsigned long cpu_hz)
00069 {
00070         volatile avr32_twi_t *twi = &AVR32_TWI;
00071         unsigned int cldiv;
00072         unsigned int ckdiv = 0;
00073 
00074         cldiv = cpu_hz / (speed * 2) - 4;
00075 
00076         while (cldiv > 255)
00077         {
00078                 ckdiv++;
00079                 cldiv /= 2;
00080         }
00081 
00082         twi->cwgr = ( cldiv | (cldiv << 8) | (ckdiv << 16) );
00083 
00084         return TWI_SUCCESS;
00085 
00086 }
00087 
00088 int twi_init(struct twi_options_t * opt)
00089 {
00090 
00091         volatile avr32_twi_t *twi = &AVR32_TWI;
00092 
00093         /* Reset, enable master transfer and disable slave transfer */
00094         twi->cr = // (1<<AVR32_TWI_CR_SWRST_OFFSET) |
00095                         (1<<AVR32_TWI_CR_MSEN_OFFSET);
00096         twi->iadr = opt->twi_addr;
00097 
00098         return twi_set_speed(opt->speed, opt->cpu_hz);
00099 
00100 }
00101 
00102 int twi_probe(char chip_addr)
00103 {
00104         volatile avr32_twi_t *twi = &AVR32_TWI;
00105         int timeout = TWI_TIMEOUT;
00106 
00107         twi->mmr = (chip_addr << 16) | (1<<AVR32_TWI_MMR_MREAD_OFFSET);
00108         twi->iadr = 0;
00109         twi->cr = (1<<AVR32_TWI_CR_START_OFFSET) | (1<<AVR32_TWI_CR_STOP_OFFSET);
00110 
00111         do {
00112                 if ((twi->sr) & (1<<AVR32_TWI_SR_RXRDY_OFFSET))
00113                 {
00114                         return TWI_SUCCESS;
00115                 }
00116         } while (!(twi->sr & (1<<AVR32_TWI_SR_TXCOMP_OFFSET)) && --timeout);
00117 
00118         return TWI_NO_CHIP_FOUND;
00119 }
00120 
00121 int twi_read(struct twi_package_t * package)
00122 {
00123         volatile avr32_twi_t *twi = &AVR32_TWI;
00124         unsigned int i = 0;
00125         unsigned int timeout = TWI_TIMEOUT;
00126 
00127         if (package->length == 0)
00128         {
00129                 return TWI_INVALID_ARGUMENT;
00130         }
00131 
00132         /* clear buffer for data */
00133         for (i = 0; i< package->length; i++)
00134                 package->buffer[i] = '_';
00135         i=0;
00136 
00137         twi->mmr = (package->chip << AVR32_TWI_MMR_DADR_OFFSET) |
00138                         ((package->addr_length &3) << 8) |
00139                         (1<<AVR32_TWI_MMR_MREAD_OFFSET);
00140         twi->iadr = package->addr;
00141 
00142         /* send start condition */
00143         twi->cr = (1<<AVR32_TWI_CR_START_OFFSET);
00144 
00145 
00146         /* get data */
00147         while (i < package->length){
00148           if (twi->sr & (1<<AVR32_TWI_SR_RXRDY_OFFSET)){
00149             package->buffer[i++] = twi->rhr; /*put the byte in the receive holding register */  
00150             //print(usart, "got one byte\n");
00151           }
00152 
00153           /* Wait for ACK */
00154           while (!(twi->sr & (1<<AVR32_TWI_SR_RXRDY_OFFSET)) && (--timeout));
00155 
00156           /* Check for timeout */
00157           if(timeout==0){
00158             return TWI_RECEIVE_NACK;    
00159           }
00160 
00161           timeout=TWI_TIMEOUT; /* reset timer */
00162         } /* end while loop */
00163 
00164         /* send stop condition */
00165         twi->cr |= (1<<AVR32_TWI_CR_STOP_OFFSET);
00166 
00167         /* add terminating char */
00168         package->buffer[i++] = '\0';
00169 
00170         if (twi->sr & (1<<AVR32_TWI_SR_NACK_OFFSET))
00171                 return TWI_RECEIVE_NACK;
00172 
00173         if (i < package->length)
00174                 return TWI_INVALID_ARGUMENT;
00175         return i;
00176 }
00177 
00178 
00179 int twi_write(struct twi_package_t * package)
00180 {
00181         volatile avr32_twi_t *twi = &AVR32_TWI;
00182         int i = 0;
00183         int timeout = TWI_TIMEOUT;
00184 
00185         /* No data to send */
00186         if (package->length == 0)
00187         {
00188                 return TWI_INVALID_ARGUMENT;
00189         }
00190 
00191         twi->cr |= (0<<AVR32_TWI_CR_MSDIS_OFFSET);
00192 
00193         /* set slave address and 3 internal address byte length */
00194         twi->mmr = (0<<AVR32_TWI_MMR_MREAD_OFFSET) | \
00195                         (package->chip << AVR32_TWI_MMR_DADR_OFFSET) | \
00196                         ((package->addr_length & 3) << 8);
00197         /* set internal address for remote chip */
00198         twi->iadr = package->addr;
00199 
00200         /* set start condition */
00201         twi->cr |= (1<<AVR32_TWI_CR_START_OFFSET);
00202 
00203         /* send data*/
00204         while (i < package->length){
00205 
00206                 if (twi->sr & (1<<AVR32_TWI_SR_TXRDY_OFFSET))
00207                         twi->thr = package->buffer[i++]; /*put the byte in the transmit holding register */
00208 
00209                 /* Wait for ACK */
00210                 while (!(twi->sr & (1<<AVR32_TWI_SR_TXCOMP_OFFSET)) && timeout--);
00211 
00212                 if(timeout==0)
00213                         return TWI_RECEIVE_NACK;
00214 
00215                 timeout=TWI_TIMEOUT; /* reset timer */
00216 
00217         }
00218 
00219 
00220         /* set stop condition */
00221         twi->cr |= (1<<AVR32_TWI_CR_STOP_OFFSET);
00222 
00223         /* NACK */
00224         if (twi->sr & (1<<AVR32_TWI_SR_NACK_OFFSET))
00225                 return TWI_SEND_NACK;
00226 
00227         /* not all bytes were sent */
00228         if (i < package->length)
00229         {
00230                 /* TIMEOUT */
00231                 return TWI_INVALID_ARGUMENT;
00232         }
00233 
00234         /* Everything went ok */
00235 
00236         return i;
00237 }
00238 

Generated on Wed Sep 26 10:45:42 2007 for AVR32107 Using TWI as a Master on the AVR32 by  doxygen 1.5.3