1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2011, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
30 /** \addtogroup twi_module Working with TWI
\r
31 * \ingroup peripherals_module
\r
32 * The TWI driver provides the interface to configure and use the TWI
\r
37 * <li> Configures a TWI peripheral to operate in master mode, at the given
\r
38 * frequency (in Hz) using TWI_Configure(). </li>
\r
39 * <li> Sends a STOP condition on the TWI using TWI_Stop().</li>
\r
40 * <li> Starts a read operation on the TWI bus with the specified slave using
\r
41 * TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever
\r
42 * a byte is available (poll using TWI_ByteReceived()).</li>
\r
43 * <li> Starts a write operation on the TWI to access the selected slave using
\r
44 * TWI_StartWrite(). A byte of data must be provided to start the write;
\r
45 * other bytes are written next.</li>
\r
46 * <li> Sends a byte of data to one of the TWI slaves on the bus using TWI_WriteByte().
\r
47 * This function must be called once before TWI_StartWrite() with the first byte of data
\r
48 * to send, then it shall be called repeatedly after that to send the remaining bytes.</li>
\r
49 * <li> Check if a byte has been received and can be read on the given TWI
\r
50 * peripheral using TWI_ByteReceived().<
\r
51 * Check if a byte has been sent using TWI_ByteSent().</li>
\r
52 * <li> Check if the current transmission is complete (the STOP has been sent)
\r
53 * using TWI_TransferComplete().</li>
\r
54 * <li> Enables & disable the selected interrupts sources on a TWI peripheral
\r
55 * using TWI_EnableIt() and TWI_DisableIt().</li>
\r
56 * <li> Get current status register of the given TWI peripheral using
\r
57 * TWI_GetStatus(). Get current status register of the given TWI peripheral, but
\r
58 * masking interrupt sources which are not currently enabled using
\r
59 * TWI_GetMaskedStatus().</li>
\r
61 * For more accurate information, please look at the TWI section of the
\r
74 * Implementation of Two Wire Interface (TWI).
\r
78 /*----------------------------------------------------------------------------
\r
80 *----------------------------------------------------------------------------*/
\r
86 /*----------------------------------------------------------------------------
\r
87 * Exported functions
\r
88 *----------------------------------------------------------------------------*/
\r
91 * \brief Configures a TWI peripheral to operate in master mode, at the given
\r
92 * frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
\r
93 * \param pTwi Pointer to an Twihs instance.
\r
94 * \param twck Desired TWI clock frequency.
\r
95 * \param mck Master clock frequency.
\r
97 void TWI_ConfigureMaster( Twihs *pTwi, uint32_t dwTwCk, uint32_t dwMCk )
\r
99 uint32_t dwCkDiv = 0 ;
\r
101 uint32_t dwOk = 0 ;
\r
103 TRACE_DEBUG( "TWI_ConfigureMaster()\n\r" ) ;
\r
106 /* SVEN: TWI Slave Mode Enabled */
\r
107 pTwi->TWIHS_CR = TWIHS_CR_SVEN ;
\r
108 /* Reset the TWI */
\r
109 pTwi->TWIHS_CR = TWIHS_CR_SWRST ;
\r
112 /* TWI Slave Mode Disabled, TWI Master Mode Disabled. */
\r
113 pTwi->TWIHS_CR = TWIHS_CR_SVDIS ;
\r
114 pTwi->TWIHS_CR = TWIHS_CR_MSDIS ;
\r
116 /* Set master mode */
\r
117 pTwi->TWIHS_CR = TWIHS_CR_MSEN ;
\r
119 /* Configure clock */
\r
122 dwClDiv = ((dwMCk / (2 * dwTwCk)) - 4) / (1<<dwCkDiv) ;
\r
124 if ( dwClDiv <= 255 )
\r
134 assert( dwCkDiv < 8 ) ;
\r
135 TRACE_DEBUG( "Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", dwCkDiv, dwClDiv ) ;
\r
137 pTwi->TWIHS_CWGR = 0 ;
\r
138 pTwi->TWIHS_CWGR = (dwCkDiv << 16) | (dwClDiv << 8) | dwClDiv ;
\r
142 * \brief Configures a TWI peripheral to operate in slave mode.
\r
143 * \param pTwi Pointer to an Twihs instance.
\r
144 * \param slaveAddress Slave address.
\r
146 void TWI_ConfigureSlave(Twihs *pTwi, uint8_t slaveAddress)
\r
150 /* TWI software reset */
\r
151 pTwi->TWIHS_CR = TWIHS_CR_SWRST;
\r
154 /* Wait at least 10 ms */
\r
155 for (i=0; i < 1000000; i++);
\r
157 /* TWI Slave Mode Disabled, TWI Master Mode Disabled*/
\r
158 pTwi->TWIHS_CR = TWIHS_CR_SVDIS | TWIHS_CR_MSDIS;
\r
160 /* Configure slave address. */
\r
161 pTwi->TWIHS_SMR = 0;
\r
162 pTwi->TWIHS_SMR = TWIHS_SMR_SADR(slaveAddress);
\r
164 /* SVEN: TWI Slave Mode Enabled */
\r
165 pTwi->TWIHS_CR = TWIHS_CR_SVEN;
\r
167 /* Wait at least 10 ms */
\r
168 for (i=0; i < 1000000; i++);
\r
169 assert( (pTwi->TWIHS_CR & TWIHS_CR_SVDIS)!= TWIHS_CR_SVDIS ) ;
\r
173 * \brief Sends a STOP condition on the TWI.
\r
174 * \param pTwi Pointer to an Twihs instance.
\r
176 void TWI_Stop( Twihs *pTwi )
\r
178 assert( pTwi != NULL ) ;
\r
180 pTwi->TWIHS_CR = TWIHS_CR_STOP;
\r
184 * \brief Starts a read operation on the TWI bus with the specified slave, it returns
\r
185 * immediately. Data must then be read using TWI_ReadByte() whenever a byte is
\r
186 * available (poll using TWI_ByteReceived()).
\r
187 * \param pTwi Pointer to an Twihs instance.
\r
188 * \param address Slave address on the bus.
\r
189 * \param iaddress Optional internal address bytes.
\r
190 * \param isize Number of internal address bytes.
\r
192 void TWI_StartRead(
\r
198 assert( pTwi != NULL ) ;
\r
199 assert( (address & 0x80) == 0 ) ;
\r
200 assert( (iaddress & 0xFF000000) == 0 ) ;
\r
201 assert( isize < 4 ) ;
\r
203 /* Set slave address and number of internal address bytes. */
\r
204 pTwi->TWIHS_MMR = 0;
\r
205 pTwi->TWIHS_MMR = (isize << 8) | TWIHS_MMR_MREAD | (address << 16);
\r
207 /* Set internal address bytes */
\r
208 pTwi->TWIHS_IADR = 0;
\r
209 pTwi->TWIHS_IADR = iaddress;
\r
211 /* Send START condition */
\r
212 pTwi->TWIHS_CR = TWIHS_CR_START;
\r
216 * \brief Reads a byte from the TWI bus. The read operation must have been started
\r
217 * using TWI_StartRead() and a byte must be available (check with TWI_ByteReceived()).
\r
218 * \param pTwi Pointer to an Twihs instance.
\r
219 * \return byte read.
\r
221 uint8_t TWI_ReadByte(Twihs *pTwi)
\r
223 assert( pTwi != NULL ) ;
\r
225 return pTwi->TWIHS_RHR;
\r
229 * \brief Sends a byte of data to one of the TWI slaves on the bus.
\r
230 * \note This function must be called once before TWI_StartWrite() with
\r
231 * the first byte of data to send, then it shall be called repeatedly
\r
232 * after that to send the remaining bytes.
\r
233 * \param pTwi Pointer to an Twihs instance.
\r
234 * \param byte Byte to send.
\r
236 void TWI_WriteByte(Twihs *pTwi, uint8_t byte)
\r
238 assert( pTwi != NULL ) ;
\r
240 pTwi->TWIHS_THR = byte;
\r
244 * \brief Starts a write operation on the TWI to access the selected slave, then
\r
245 * returns immediately. A byte of data must be provided to start the write;
\r
246 * other bytes are written next.
\r
247 * after that to send the remaining bytes.
\r
248 * \param pTwi Pointer to an Twihs instance.
\r
249 * \param address Address of slave to acccess on the bus.
\r
250 * \param iaddress Optional slave internal address.
\r
251 * \param isize Number of internal address bytes.
\r
252 * \param byte First byte to send.
\r
254 void TWI_StartWrite(
\r
261 assert( pTwi != NULL ) ;
\r
262 assert( (address & 0x80) == 0 ) ;
\r
263 assert( (iaddress & 0xFF000000) == 0 ) ;
\r
264 assert( isize < 4 ) ;
\r
266 /* Set slave address and number of internal address bytes. */
\r
267 pTwi->TWIHS_MMR = 0;
\r
268 pTwi->TWIHS_MMR = (isize << 8) | (address << 16);
\r
270 /* Set internal address bytes. */
\r
271 pTwi->TWIHS_IADR = 0;
\r
272 pTwi->TWIHS_IADR = iaddress;
\r
274 /* Write first byte to send.*/
\r
275 TWI_WriteByte(pTwi, byte);
\r
279 * \brief Check if a byte have been receiced from TWI.
\r
280 * \param pTwi Pointer to an Twihs instance.
\r
281 * \return 1 if a byte has been received and can be read on the given TWI
\r
282 * peripheral; otherwise, returns 0. This function resets the status register.
\r
284 uint8_t TWI_ByteReceived(Twihs *pTwi)
\r
286 return ((pTwi->TWIHS_SR & TWIHS_SR_RXRDY) == TWIHS_SR_RXRDY);
\r
290 * \brief Check if a byte have been sent to TWI.
\r
291 * \param pTwi Pointer to an Twihs instance.
\r
292 * \return 1 if a byte has been sent so another one can be stored for
\r
293 * transmission; otherwise returns 0. This function clears the status register.
\r
295 uint8_t TWI_ByteSent(Twihs *pTwi)
\r
297 return ((pTwi->TWIHS_SR & TWIHS_SR_TXRDY) == TWIHS_SR_TXRDY);
\r
301 * \brief Check if current transmission is complet.
\r
302 * \param pTwi Pointer to an Twihs instance.
\r
303 * \return 1 if the current transmission is complete (the STOP has been sent);
\r
304 * otherwise returns 0.
\r
306 uint8_t TWI_TransferComplete(Twihs *pTwi)
\r
308 return ((pTwi->TWIHS_SR & TWIHS_SR_TXCOMP) == TWIHS_SR_TXCOMP);
\r
312 * \brief Enables the selected interrupts sources on a TWI peripheral.
\r
313 * \param pTwi Pointer to an Twihs instance.
\r
314 * \param sources Bitwise OR of selected interrupt sources.
\r
316 void TWI_EnableIt(Twihs *pTwi, uint32_t sources)
\r
318 assert( pTwi != NULL ) ;
\r
319 assert( (sources & 0xFFFFF088) == 0 ) ;
\r
321 pTwi->TWIHS_IER = sources;
\r
325 * \brief Disables the selected interrupts sources on a TWI peripheral.
\r
326 * \param pTwi Pointer to an Twihs instance.
\r
327 * \param sources Bitwise OR of selected interrupt sources.
\r
329 void TWI_DisableIt(Twihs *pTwi, uint32_t sources)
\r
331 assert( pTwi != NULL ) ;
\r
332 assert( (sources & 0xFFFFF088) == 0 ) ;
\r
334 pTwi->TWIHS_IDR = sources;
\r
338 * \brief Get the current status register of the given TWI peripheral.
\r
339 * \note This resets the internal value of the status register, so further
\r
340 * read may yield different values.
\r
341 * \param pTwi Pointer to an Twihs instance.
\r
342 * \return TWI status register.
\r
344 uint32_t TWI_GetStatus(Twihs *pTwi)
\r
346 assert( pTwi != NULL ) ;
\r
348 return pTwi->TWIHS_SR;
\r
352 * \brief Returns the current status register of the given TWI peripheral, but
\r
353 * masking interrupt sources which are not currently enabled.
\r
354 * \note This resets the internal value of the status register, so further
\r
355 * read may yield different values.
\r
356 * \param pTwi Pointer to an Twihs instance.
\r
358 uint32_t TWI_GetMaskedStatus(Twihs *pTwi)
\r
362 assert( pTwi != NULL ) ;
\r
364 status = pTwi->TWIHS_SR;
\r
365 status &= pTwi->TWIHS_IMR;
\r
371 * \brief Sends a STOP condition. STOP Condition is sent just after completing
\r
372 * the current byte transmission in master read mode.
\r
373 * \param pTwi Pointer to an Twihs instance.
\r
375 void TWI_SendSTOPCondition(Twihs *pTwi)
\r
377 assert( pTwi != NULL ) ;
\r
379 pTwi->TWIHS_CR |= TWIHS_CR_STOP;
\r