aboutsummaryrefslogtreecommitdiff
path: root/LUFA/Drivers/Peripheral
diff options
context:
space:
mode:
Diffstat (limited to 'LUFA/Drivers/Peripheral')
-rw-r--r--LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h24
-rw-r--r--LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c63
-rw-r--r--LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h76
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);