diff options
Diffstat (limited to 'LUFA/Drivers/Peripheral/AVR8')
| -rw-r--r-- | LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h | 24 | ||||
| -rw-r--r-- | LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c | 63 | ||||
| -rw-r--r-- | LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h | 76 |
3 files changed, 100 insertions, 63 deletions
diff --git a/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h b/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h index 7f519d3b..639b3c3b 100644 --- a/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h +++ b/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h @@ -97,15 +97,23 @@ /* Public Interface - May be used in end-application: */ /* Macros: */ - /** Macro for calculating the baud value from a given baud rate when the U2X (double speed) bit is + /** Macro for calculating the baud value from a given baud rate when the \c U2X (double speed) bit is * not set. + * + * \param[in] Baud Target serial UART baud rate. + * + * \return Closest UBRR register value for the given UART frequency. */ - #define SERIAL_UBBRVAL(baud) ((((F_CPU / 16) + (baud / 2)) / (baud)) - 1) + #define SERIAL_UBBRVAL(Baud) ((((F_CPU / 16) + (Baud / 2)) / (Baud)) - 1) - /** Macro for calculating the baud value from a given baud rate when the U2X (double speed) bit is + /** Macro for calculating the baud value from a given baud rate when the \c U2X (double speed) bit is * set. + * + * \param[in] Baud Target serial UART baud rate. + * + * \return Closest UBRR register value for the given UART frequency. */ - #define SERIAL_2X_UBBRVAL(baud) ((((F_CPU / 8) + (baud / 2)) / (baud)) - 1) + #define SERIAL_2X_UBBRVAL(Baud) ((((F_CPU / 8) + (Baud / 2)) / (Baud)) - 1) /* Function Prototypes: */ /** Transmits a given string located in program space (FLASH) through the USART. @@ -169,8 +177,8 @@ * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own * line buffering. * - * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL stdio - * and stdin will be configured to use the USART. + * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL, \c stdout + * and \c stdin will be configured to use the USART. * * \pre The USART must first be configured via a call to \ref Serial_Init() before the stream is used. */ @@ -189,8 +197,8 @@ /** Identical to \ref Serial_CreateStream(), except that reads are blocking until the calling stream function terminates * the transfer. * - * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL stdio - * and stdin will be configured to use the USART. + * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL, \c stdout + * and \c stdin will be configured to use the USART. * * \pre The USART must first be configured via a call to \ref Serial_Init() before the stream is used. */ diff --git a/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c b/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c index 2f65921c..d6db37d6 100644 --- a/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c +++ b/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c @@ -97,34 +97,69 @@ uint8_t TWI_StartTransmission(const uint8_t SlaveAddress, } } +bool TWI_SendByte(const uint8_t Byte) +{ + TWDR = Byte; + TWCR = ((1 << TWINT) | (1 << TWEN)); + while (!(TWCR & (1 << TWINT))); + + return ((TWSR & TW_STATUS_MASK) == TW_MT_DATA_ACK); +} + +bool TWI_ReceiveByte(uint8_t* const Byte, + const bool LastByte) +{ + uint8_t TWCRMask; + + if (LastByte) + TWCRMask = ((1 << TWINT) | (1 << TWEN)); + else + TWCRMask = ((1 << TWINT) | (1 << TWEN) | (1 << TWEA)); + + TWCR = TWCRMask; + while (!(TWCR & (1 << TWINT))); + *Byte = TWDR; + + uint8_t Status = (TWSR & TW_STATUS_MASK); + + return ((LastByte) ? (Status == TW_MR_DATA_NACK) : (Status == TW_MR_DATA_ACK)); +} + uint8_t TWI_ReadPacket(const uint8_t SlaveAddress, const uint8_t TimeoutMS, const uint8_t* InternalAddress, - const uint8_t InternalAddressLen, + uint8_t InternalAddressLen, uint8_t* Buffer, uint8_t Length) { uint8_t ErrorCode; - if ((ErrorCode = TWI_WritePacket(SlaveAddress, TimeoutMS, InternalAddress, InternalAddressLen, - NULL, 0)) != TWI_ERROR_NoError) - { - return ErrorCode; - } - - if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_READ, - TimeoutMS)) == TWI_ERROR_NoError) + if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE, + TimeoutMS)) == TWI_ERROR_NoError) { - while (Length--) + while (InternalAddressLen--) { - if (!(TWI_ReceiveByte(Buffer++, (Length == 0)))) - { + if (!(TWI_SendByte(*(InternalAddress++)))) + { ErrorCode = TWI_ERROR_SlaveNAK; break; } } - TWI_StopTransmission(); + if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_READ, + TimeoutMS)) == TWI_ERROR_NoError) + { + while (Length--) + { + if (!(TWI_ReceiveByte(Buffer++, (Length == 0)))) + { + ErrorCode = TWI_ERROR_SlaveNAK; + break; + } + } + + TWI_StopTransmission(); + } } return ErrorCode; @@ -145,7 +180,7 @@ uint8_t TWI_WritePacket(const uint8_t SlaveAddress, while (InternalAddressLen--) { if (!(TWI_SendByte(*(InternalAddress++)))) - { + { ErrorCode = TWI_ERROR_SlaveNAK; break; } diff --git a/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h b/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h index df63b6ad..eb33ae56 100644 --- a/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h +++ b/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h @@ -52,8 +52,8 @@ * * <b>Low Level API Example:</b> * \code - * // Initialize the TWI driver before first use - * TWI_Init(TWI_BIT_PRESCALE_1, 10); + * // Initialize the TWI driver before first use at 200KHz + * TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 200000)); * * // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout * if (TWI_StartTransmission(0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError) @@ -91,8 +91,8 @@ * * <b>High Level API Example:</b> * \code - * // Initialize the TWI driver before first use - * TWI_Init(TWI_BIT_PRESCALE_1, 10); + * // Initialize the TWI driver before first use at 200KHz + * TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 200000)); * * // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout * uint8_t InternalWriteAddress = 0xDC; @@ -143,12 +143,12 @@ /** TWI slave device address mask for a read session. Mask with a slave device base address to obtain * the correct TWI bus address for the slave device when reading data from it. */ - #define TWI_ADDRESS_READ 0x00 + #define TWI_ADDRESS_READ 0x01 /** TWI slave device address mask for a write session. Mask with a slave device base address to obtain * the correct TWI bus address for the slave device when writing data to it. */ - #define TWI_ADDRESS_WRITE 0x01 + #define TWI_ADDRESS_WRITE 0x00 /** Mask to retrieve the base address for a TWI device, which can then be ORed with \ref TWI_ADDRESS_READ * or \ref TWI_ADDRESS_WRITE to obtain the device's read and write address respectively. @@ -167,6 +167,17 @@ /** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 64. */ #define TWI_BIT_PRESCALE_64 ((1 << TWPS1) | (1 << TWPS0)) + /** Calculates the length of each bit on the TWI bus for a given target frequency. This may be used with + * the \ref TWI_Init() function to convert a bus frequency to a number of clocks for the \c BitLength + * parameter. + * + * \param[in] Prescaler Prescaler set on the TWI bus. + * \param[in] Frequency Desired TWI bus frequency in Hz. + * + * \return Bit length in clocks for the given TWI bus frequency at the given prescaler value. + */ + #define TWI_BITLENGTH_FROM_FREQ(Prescale, Frequency) ((((F_CPU / (Prescale)) / (Frequency)) - 16) / 2) + /* Enums: */ /** Enum for the possible return codes of the TWI transfer start routine and other dependant TWI functions. */ enum TWI_ErrorCodes_t @@ -215,20 +226,24 @@ TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN)); } + /* Function Prototypes: */ + /** Begins a master mode TWI bus communication with the given slave device address. + * + * \param[in] SlaveAddress Address of the slave TWI device to communicate with. + * \param[in] TimeoutMS Timeout period within which the slave must respond, in milliseconds. + * + * \return A value from the \ref TWI_ErrorCodes_t enum. + */ + uint8_t TWI_StartTransmission(const uint8_t SlaveAddress, + const uint8_t TimeoutMS); + /** Sends a byte to the currently addressed device on the TWI bus. * * \param[in] Byte Byte to send to the currently addressed device * * \return Boolean \c true if the recipient ACKed the byte, \c false otherwise */ - static inline bool TWI_SendByte(const uint8_t Byte) - { - TWDR = Byte; - TWCR = ((1 << TWINT) | (1 << TWEN)); - while (!(TWCR & (1 << TWINT))); - - return ((TWSR & TW_STATUS_MASK) == TW_MT_DATA_ACK); - } + bool TWI_SendByte(const uint8_t Byte); /** Receives a byte from the currently addressed device on the TWI bus. * @@ -237,32 +252,11 @@ * * \return Boolean \c true if the byte reception successfully completed, \c false otherwise. */ - static inline bool TWI_ReceiveByte(uint8_t* const Byte, - const bool LastByte) - { - uint8_t TWCRMask = ((1 << TWINT) | (1 << TWEN)); - - if (!(LastByte)) - TWCRMask |= (1 << TWEA); - - TWCR = TWCRMask; - while (!(TWCR & (1 << TWINT))); - *Byte = TWDR; - - return ((TWSR & TW_STATUS_MASK) == TW_MR_DATA_ACK); - } - - /* Function Prototypes: */ - /** Begins a master mode TWI bus communication with the given slave device address. - * - * \param[in] SlaveAddress Address of the slave TWI device to communicate with. - * \param[in] TimeoutMS Timeout period within which the slave must respond, in milliseconds. - * - * \return A value from the \ref TWI_ErrorCodes_t enum. - */ - uint8_t TWI_StartTransmission(const uint8_t SlaveAddress, - const uint8_t TimeoutMS); - + bool TWI_ReceiveByte(uint8_t* const Byte, + const bool LastByte) ATTR_NON_NULL_PTR_ARG(1); + bool TWI_ReceiveByte(uint8_t* const Byte, + const bool LastByte); + /** High level function to perform a complete packet transfer over the TWI bus to the specified * device. * @@ -278,7 +272,7 @@ uint8_t TWI_ReadPacket(const uint8_t SlaveAddress, const uint8_t TimeoutMS, const uint8_t* InternalAddress, - const uint8_t InternalAddressLen, + uint8_t InternalAddressLen, uint8_t* Buffer, uint8_t Length) ATTR_NON_NULL_PTR_ARG(3); |
