123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- /***************************************************************************//**
- * @file
- * @brief Inter-intergrated circuit (I2C) peripheral API
- * @author Energy Micro AS
- * @version 3.0.0
- *******************************************************************************
- * @section License
- * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
- *******************************************************************************
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- *
- * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
- * obligation to support this Software. Energy Micro AS is providing the
- * Software "AS IS", with no express or implied warranties of any kind,
- * including, but not limited to, any implied warranties of merchantability
- * or fitness for any particular purpose or warranties against infringement
- * of any proprietary rights of a third party.
- *
- * Energy Micro AS will not be liable for any consequential, incidental, or
- * special damages, or any other relief, or for any claim by any third party,
- * arising from your use of this Software.
- *
- ******************************************************************************/
- #ifndef __EM_I2C_H
- #define __EM_I2C_H
- #include <stdbool.h>
- #include "em_part.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- /***************************************************************************//**
- * @addtogroup EM_Library
- * @{
- ******************************************************************************/
- /***************************************************************************//**
- * @addtogroup I2C
- * @{
- ******************************************************************************/
- /*******************************************************************************
- ******************************* DEFINES ***********************************
- ******************************************************************************/
- /**
- * @brief
- * Standard mode max frequency assuming using 4:4 ratio for Nlow:Nhigh.
- * @details
- * From I2C specification: Min Tlow = 4.7us, min Thigh = 4.0us,
- * max Trise=1.0us, max Tfall=0.3us. Since ratio is 4:4, have to use
- * worst case value of Tlow or Thigh as base.
- *
- * 1/(Tlow + Thigh + 1us + 0.3us) = 1/(4.7 + 4.7 + 1.3)us = 93458Hz
- */
- #define I2C_FREQ_STANDARD_MAX 93500
- /**
- * @brief
- * Fast mode max frequency assuming using 6:3 ratio for Nlow:Nhigh.
- * @details
- * From I2C specification: Min Tlow = 1.3us, min Thigh = 0.6us,
- * max Trise=0.3us, max Tfall=0.3us. Since ratio is 6:3, have to use
- * worst case value of Tlow or 2xThigh as base.
- *
- * 1/(Tlow + Thigh + 0.3us + 0.3us) = 1/(1.3 + 0.65 + 0.6)us = 392157Hz
- */
- #define I2C_FREQ_FAST_MAX 392500
- /**
- * @brief
- * Fast mode+ max frequency assuming using 11:6 ratio for Nlow:Nhigh.
- * @details
- * From I2C specification: Min Tlow = 0.5us, min Thigh = 0.26us,
- * max Trise=0.012us, max Tfall=0.12us. Since ratio is 11:6, have to use
- * worst case value of Tlow or (11/6)xThigh as base.
- *
- * 1/(Tlow + Thigh + 0.12us + 0.12us) = 1/(0.5 + 0.273 + 0.24)us = 987167Hz
- */
- #define I2C_FREQ_FASTPLUS_MAX 987500
- /**
- * @brief
- * Indicate plain write sequence: S+ADDR(W)+DATA0+P.
- * @details
- * @li S - Start
- * @li ADDR(W) - address with W/R bit cleared
- * @li DATA0 - Data taken from buffer with index 0
- * @li P - Stop
- */
- #define I2C_FLAG_WRITE 0x0001
- /**
- * @brief
- * Indicate plain read sequence: S+ADDR(R)+DATA0+P.
- * @details
- * @li S - Start
- * @li ADDR(R) - address with W/R bit set
- * @li DATA0 - Data read into buffer with index 0
- * @li P - Stop
- */
- #define I2C_FLAG_READ 0x0002
- /**
- * @brief
- * Indicate combined write/read sequence: S+ADDR(W)+DATA0+Sr+ADDR(R)+DATA1+P.
- * @details
- * @li S - Start
- * @li Sr - Repeated start
- * @li ADDR(W) - address with W/R bit cleared
- * @li ADDR(R) - address with W/R bit set
- * @li DATAn - Data written from/read into buffer with index n
- * @li P - Stop
- */
- #define I2C_FLAG_WRITE_READ 0x0004
- /**
- * @brief
- * Indicate write sequence using two buffers: S+ADDR(W)+DATA0+DATA1+P.
- * @details
- * @li S - Start
- * @li ADDR(W) - address with W/R bit cleared
- * @li DATAn - Data written from buffer with index n
- * @li P - Stop
- */
- #define I2C_FLAG_WRITE_WRITE 0x0008
- /** Use 10 bit address. */
- #define I2C_FLAG_10BIT_ADDR 0x0010
- /*******************************************************************************
- ******************************** ENUMS ************************************
- ******************************************************************************/
- /** Clock low to high ratio settings. */
- typedef enum
- {
- i2cClockHLRStandard = _I2C_CTRL_CLHR_STANDARD, /**< Ratio is 4:4 */
- i2cClockHLRAsymetric = _I2C_CTRL_CLHR_ASYMMETRIC, /**< Ratio is 6:3 */
- i2cClockHLRFast = _I2C_CTRL_CLHR_FAST /**< Ratio is 11:3 */
- } I2C_ClockHLR_TypeDef;
- /** Return codes for single master mode transfer function. */
- typedef enum
- {
- /* In progress code (>0) */
- i2cTransferInProgress = 1, /**< Transfer in progress. */
- /* Complete code (=0) */
- i2cTransferDone = 0, /**< Transfer completed successfully. */
- /* Transfer error codes (<0) */
- i2cTransferNack = -1, /**< NACK received during transfer. */
- i2cTransferBusErr = -2, /**< Bus error during transfer (misplaced START/STOP). */
- i2cTransferArbLost = -3, /**< Arbitration lost during transfer. */
- i2cTransferUsageFault = -4, /**< Usage fault. */
- i2cTransferSwFault = -5 /**< SW fault. */
- } I2C_TransferReturn_TypeDef;
- /*******************************************************************************
- ******************************* STRUCTS ***********************************
- ******************************************************************************/
- /** I2C initialization structure. */
- typedef struct
- {
- /** Enable I2C peripheral when init completed. */
- bool enable;
- /** Set to master (true) or slave (false) mode */
- bool master;
- /**
- * I2C reference clock assumed when configuring bus frequency setup.
- * Set it to 0 if currently configurated reference clock shall be used
- * This parameter is only applicable if operating in master mode.
- */
- uint32_t refFreq;
- /**
- * (Max) I2C bus frequency to use. This parameter is only applicable
- * if operating in master mode.
- */
- uint32_t freq;
- /** Clock low/high ratio control. */
- I2C_ClockHLR_TypeDef clhr;
- } I2C_Init_TypeDef;
- /** Suggested default config for I2C init structure. */
- #define I2C_INIT_DEFAULT \
- { true, /* Enable when init done */ \
- true, /* Set to master mode */ \
- 0, /* Use currently configured reference clock */ \
- I2C_FREQ_STANDARD_MAX, /* Set to standard rate assuring being */ \
- /* within I2C spec */ \
- i2cClockHLRStandard /* Set to use 4:4 low/high duty cycle */ \
- }
- /**
- * @brief
- * Master mode transfer message structure used to define a complete
- * I2C transfer sequence (from start to stop).
- * @details
- * The structure allows for defining the following types of sequences,
- * please refer to defines for sequence details.
- * @li #I2C_FLAG_READ - data read into buf[0].data
- * @li #I2C_FLAG_WRITE - data written from buf[0].data
- * @li #I2C_FLAG_WRITE_READ - data written from buf[0].data and read
- * into buf[1].data
- * @li #I2C_FLAG_WRITE_WRITE - data written from buf[0].data and
- * buf[1].data
- */
- typedef struct
- {
- /**
- * @brief
- * Address to use after (repeated) start.
- * @details
- * Layout details, A = address bit, X = don't care bit (set to 0):
- * @li 7 bit address - use format AAAA AAAX.
- * @li 10 bit address - use format XXXX XAAX AAAA AAAA
- */
- uint16_t addr;
- /** Flags defining sequence type and details, see I2C_FLAG_... defines. */
- uint16_t flags;
- /**
- * Buffers used to hold data to send from or receive into depending
- * on sequence type.
- */
- struct
- {
- /** Buffer used for data to transmit/receive, must be @p len long. */
- uint8_t *data;
- /**
- * Number of bytes in @p data to send or receive. Notice that when
- * receiving data to this buffer, at least 1 byte must be received.
- * Setting @p len to 0 in the receive case is considered a usage fault.
- * Transmitting 0 bytes is legal, in which case only the address
- * is transmitted after the start condition.
- */
- uint16_t len;
- } buf[2];
- } I2C_TransferSeq_TypeDef;
- /*******************************************************************************
- ***************************** PROTOTYPES **********************************
- ******************************************************************************/
- uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c);
- void I2C_BusFreqSet(I2C_TypeDef *i2c,
- uint32_t refFreq,
- uint32_t freq,
- I2C_ClockHLR_TypeDef type);
- void I2C_Enable(I2C_TypeDef *i2c, bool enable);
- void I2C_Init(I2C_TypeDef *i2c, const I2C_Init_TypeDef *init);
- /***************************************************************************//**
- * @brief
- * Clear one or more pending I2C interrupts.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @param[in] flags
- * Pending I2C interrupt source to clear. Use a bitwse logic OR combination of
- * valid interrupt flags for the I2C module (I2C_IF_nnn).
- ******************************************************************************/
- __STATIC_INLINE void I2C_IntClear(I2C_TypeDef *i2c, uint32_t flags)
- {
- i2c->IFC = flags;
- }
- /***************************************************************************//**
- * @brief
- * Disable one or more I2C interrupts.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @param[in] flags
- * I2C interrupt sources to disable. Use a bitwise logic OR combination of
- * valid interrupt flags for the I2C module (I2C_IF_nnn).
- ******************************************************************************/
- __STATIC_INLINE void I2C_IntDisable(I2C_TypeDef *i2c, uint32_t flags)
- {
- i2c->IEN &= ~(flags);
- }
- /***************************************************************************//**
- * @brief
- * Enable one or more I2C interrupts.
- *
- * @note
- * Depending on the use, a pending interrupt may already be set prior to
- * enabling the interrupt. Consider using I2C_IntClear() prior to enabling
- * if such a pending interrupt should be ignored.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @param[in] flags
- * I2C interrupt sources to enable. Use a bitwise logic OR combination of
- * valid interrupt flags for the I2C module (I2C_IF_nnn).
- ******************************************************************************/
- __STATIC_INLINE void I2C_IntEnable(I2C_TypeDef *i2c, uint32_t flags)
- {
- i2c->IEN |= flags;
- }
- /***************************************************************************//**
- * @brief
- * Get pending I2C interrupt flags.
- *
- * @note
- * The event bits are not cleared by the use of this function.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @return
- * I2C interrupt sources pending. A bitwise logic OR combination of valid
- * interrupt flags for the I2C module (I2C_IF_nnn).
- ******************************************************************************/
- __STATIC_INLINE uint32_t I2C_IntGet(I2C_TypeDef *i2c)
- {
- return(i2c->IF);
- }
- /***************************************************************************//**
- * @brief
- * Set one or more pending I2C interrupts from SW.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @param[in] flags
- * I2C interrupt sources to set to pending. Use a bitwise logic OR combination
- * of valid interrupt flags for the I2C module (I2C_IF_nnn).
- ******************************************************************************/
- __STATIC_INLINE void I2C_IntSet(I2C_TypeDef *i2c, uint32_t flags)
- {
- i2c->IFS = flags;
- }
- void I2C_Reset(I2C_TypeDef *i2c);
- /***************************************************************************//**
- * @brief
- * Get slave address used for I2C peripheral (when operating in slave mode).
- *
- * @details
- * For 10 bit addressing mode, the address is split in two bytes, and only
- * the first byte setting is fetched, effectively only controlling the 2 most
- * significant bits of the 10 bit address. Full handling of 10 bit addressing
- * in slave mode requires additional SW handling.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @return
- * I2C slave address in use. The 7 most significant bits define the actual
- * address, the least significant bit is reserved and always returned as 0.
- ******************************************************************************/
- __STATIC_INLINE uint8_t I2C_SlaveAddressGet(I2C_TypeDef *i2c)
- {
- return((uint8_t)(i2c->SADDR));
- }
- /***************************************************************************//**
- * @brief
- * Set slave address to use for I2C peripheral (when operating in slave mode).
- *
- * @details
- * For 10 bit addressing mode, the address is split in two bytes, and only
- * the first byte is set, effectively only controlling the 2 most significant
- * bits of the 10 bit address. Full handling of 10 bit addressing in slave
- * mode requires additional SW handling.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @param[in] addr
- * I2C slave address to use. The 7 most significant bits define the actual
- * address, the least significant bit is reserved and always set to 0.
- ******************************************************************************/
- __STATIC_INLINE void I2C_SlaveAddressSet(I2C_TypeDef *i2c, uint8_t addr)
- {
- i2c->SADDR = (uint32_t)addr & 0xfe;
- }
- /***************************************************************************//**
- * @brief
- * Get slave address mask used for I2C peripheral (when operating in slave
- * mode).
- *
- * @details
- * The address mask defines how the comparator works. A bit position with
- * value 0 means that the corresponding slave address bit is ignored during
- * comparison (don't care). A bit position with value 1 means that the
- * corresponding slave address bit must match.
- *
- * For 10 bit addressing mode, the address is split in two bytes, and only
- * the mask for the first address byte is fetched, effectively only
- * controlling the 2 most significant bits of the 10 bit address.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @return
- * I2C slave address mask in use. The 7 most significant bits define the
- * actual address mask, the least significant bit is reserved and always
- * returned as 0.
- ******************************************************************************/
- __STATIC_INLINE uint8_t I2C_SlaveAddressMaskGet(I2C_TypeDef *i2c)
- {
- return((uint8_t)(i2c->SADDRMASK));
- }
- /***************************************************************************//**
- * @brief
- * Set slave address mask used for I2C peripheral (when operating in slave
- * mode).
- *
- * @details
- * The address mask defines how the comparator works. A bit position with
- * value 0 means that the corresponding slave address bit is ignored during
- * comparison (don't care). A bit position with value 1 means that the
- * corresponding slave address bit must match.
- *
- * For 10 bit addressing mode, the address is split in two bytes, and only
- * the mask for the first address byte is set, effectively only controlling
- * the 2 most significant bits of the 10 bit address.
- *
- * @param[in] i2c
- * Pointer to I2C peripheral register block.
- *
- * @param[in] mask
- * I2C slave address mask to use. The 7 most significant bits define the
- * actual address mask, the least significant bit is reserved and should
- * be 0.
- ******************************************************************************/
- __STATIC_INLINE void I2C_SlaveAddressMaskSet(I2C_TypeDef *i2c, uint8_t mask)
- {
- i2c->SADDRMASK = (uint32_t)mask & 0xfe;
- }
- I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c);
- I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c,
- I2C_TransferSeq_TypeDef *seq);
- /** @} (end addtogroup I2C) */
- /** @} (end addtogroup EM_Library) */
- #ifdef __cplusplus
- }
- #endif
- #endif /* __EM_I2C_H */
|