Convert over internal pseudo-function macros to true inline functions for added type-safety and compile-checking.

pull/1469/head
Dean Camera 14 years ago
parent 2461ae508c
commit 9b0e4b8356

@ -45,25 +45,32 @@
/* Macros: */
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
#define LEDMASK_USB_NOTREADY LEDS_LED1
#define LEDMASK_USB_NOTREADY LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
#define Req_InitiateAbortBulkOut 0x01
#define Req_CheckAbortBulkOutStatus 0x02
#define Req_InitiateAbortBulkIn 0x03
#define Req_CheckAbortBulkInStatus 0x04
#define Req_InitiateClear 0x05
#define Req_CheckClearStatus 0x06
#define Req_GetCapabilities 0x07
#define Req_IndicatorPulse 0x40
#define Req_InitiateAbortBulkOut 0x01
#define Req_CheckAbortBulkOutStatus 0x02
#define Req_InitiateAbortBulkIn 0x03
#define Req_CheckAbortBulkInStatus 0x04
#define Req_InitiateClear 0x05
#define Req_CheckClearStatus 0x06
#define Req_GetCapabilities 0x07
#define Req_IndicatorPulse 0x40
#define TMC_REQUEST_STATUS_SUCCESS 0x01
#define TMC_REQUEST_STATUS_PENDING 0x02
#define TMC_REQUEST_STATUS_FAILED 0x80
#define TMC_REQUEST_STATUS_NOTRANSFER 0x81
#define TMC_REQUEST_STATUS_NOCHECKINITIATED 0x82
#define TMC_REQUEST_STATUS_CHECKINPROGRESS 0x83
/* Function Prototypes: */
void SetupHardware(void);

@ -79,6 +79,44 @@
#define DATAFLASH_PAGES // TODO: Replace with the total number of pages inside one of the Dataflash ICs
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The AVR's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void)
{
DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
}
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Dataflash_GetSelectedChip(void)
{
return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
}
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
static inline void Dataflash_SelectChip(const uint8_t ChipMask)
{
DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask);
}
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
static inline void Dataflash_DeselectChip(void)
{
Dataflash_SelectChip(DATAFLASH_NO_CHIP);
}
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
@ -105,6 +143,28 @@
#endif
}
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void)
{
uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
Dataflash_DeselectChip();
Dataflash_SelectChip(SelectedChipMask);
}
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void)
{
Dataflash_ToggleSelectedChipCS();
Dataflash_SendByte(DF_CMD_GETSTATUS);
while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
Dataflash_ToggleSelectedChipCS();
}
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-byte address.
*

@ -70,7 +70,7 @@
/* Includes: */
#include "../Peripheral/SPI.h"
#include "../../Common/Common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
@ -91,34 +91,59 @@
*/
#define DATAFLASH_CHIP_MASK(index) __GET_DATAFLASH_MASK(index)
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void);
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(uint8_t ChipMask);
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void);
#else
#define Dataflash_GetSelectedChip() (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK)
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The AVR's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void);
#define Dataflash_SelectChip(mask) MACROS{ DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT \
& ~DATAFLASH_CHIPCS_MASK) | (mask)); }MACROE
#define Dataflash_DeselectChip() Dataflash_SelectChip(DATAFLASH_NO_CHIP)
#endif
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
* the total number of pages contained in the boards dataflash ICs, all dataflash ICs
* are deselected.
*
* \param[in] PageAddress Address of the page to manipulate, ranging from
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
*/
static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress);
/* Inline Functions: */
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void);
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void);
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-byte address.
*
* \param[in] PageAddress Page address within the selected dataflash IC
* \param[in] BufferByte Address within the dataflash's buffer
*/
static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
const uint16_t BufferByte);
/** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
*
* \param[in] Byte of data to send to the dataflash
@ -171,58 +196,6 @@
#else
#error The selected board does not contain a dataflash IC.
#endif
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The AVR's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void)
{
DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
}
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void)
{
uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
Dataflash_DeselectChip();
Dataflash_SelectChip(SelectedChipMask);
}
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void)
{
Dataflash_ToggleSelectedChipCS();
Dataflash_SendByte(DF_CMD_GETSTATUS);
while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
Dataflash_ToggleSelectedChipCS();
}
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
* the total number of pages contained in the boards dataflash ICs, all dataflash ICs
* are deselected.
*
* \param[in] PageAddress Address of the page to manipulate, ranging from
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
*/
static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress);
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-byte address.
*
* \param[in] PageAddress Page address within the selected dataflash IC.
* \param[in] BufferByte Address within the dataflash's buffer.
*/
static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
const uint16_t BufferByte);
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)

@ -85,6 +85,44 @@
#define DATAFLASH_PAGES 8192
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The AVR's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void)
{
DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
}
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Dataflash_GetSelectedChip(void)
{
return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
}
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
static inline void Dataflash_SelectChip(const uint8_t ChipMask)
{
DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask);
}
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
static inline void Dataflash_DeselectChip(void)
{
Dataflash_SelectChip(DATAFLASH_NO_CHIP);
}
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
@ -104,6 +142,28 @@
Dataflash_SelectChip(DATAFLASH_CHIP1);
}
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void)
{
uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
Dataflash_DeselectChip();
Dataflash_SelectChip(SelectedChipMask);
}
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void)
{
Dataflash_ToggleSelectedChipCS();
Dataflash_SendByte(DF_CMD_GETSTATUS);
while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
Dataflash_ToggleSelectedChipCS();
}
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-byte address.
*

@ -85,6 +85,44 @@
#define DATAFLASH_PAGES 8192
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The AVR's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void)
{
DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
}
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Dataflash_GetSelectedChip(void)
{
return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
}
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
static inline void Dataflash_SelectChip(const uint8_t ChipMask)
{
DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask);
}
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
static inline void Dataflash_DeselectChip(void)
{
Dataflash_SelectChip(DATAFLASH_NO_CHIP);
}
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
@ -103,6 +141,28 @@
Dataflash_SelectChip(DATAFLASH_CHIP1);
}
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void)
{
uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
Dataflash_DeselectChip();
Dataflash_SelectChip(SelectedChipMask);
}
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void)
{
Dataflash_ToggleSelectedChipCS();
Dataflash_SendByte(DF_CMD_GETSTATUS);
while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
Dataflash_ToggleSelectedChipCS();
}
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-byte address.

@ -85,6 +85,44 @@
#define DATAFLASH_PAGES 8192
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The AVR's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void)
{
DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
}
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Dataflash_GetSelectedChip(void)
{
return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
}
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
static inline void Dataflash_SelectChip(const uint8_t ChipMask)
{
DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask);
}
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
static inline void Dataflash_DeselectChip(void)
{
Dataflash_SelectChip(DATAFLASH_NO_CHIP);
}
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
@ -104,6 +142,28 @@
Dataflash_SelectChip(DATAFLASH_CHIP1);
}
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void)
{
uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
Dataflash_DeselectChip();
Dataflash_SelectChip(SelectedChipMask);
}
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void)
{
Dataflash_ToggleSelectedChipCS();
Dataflash_SendByte(DF_CMD_GETSTATUS);
while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
Dataflash_ToggleSelectedChipCS();
}
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-byte address.
*

@ -86,18 +86,18 @@
/** Maximum returnable temperature from the \ref Temperature_GetTemperature() function. */
#define TEMP_MAX_TEMP ((TEMP_TABLE_SIZE - 1) + TEMP_TABLE_OFFSET)
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Initializes the temperature sensor driver, including setting up the appropriate ADC channel.
* This must be called before any other temperature sensor routines.
*
* \pre The ADC itself (not the ADC channel) must be configured separately before calling the
* temperature sensor functions.
*/
static inline void Temperature_Init(void);
#else
#define Temperature_Init() ADC_SetupChannel(TEMP_ADC_CHANNEL);
#endif
/* Inline Functions: */
/** Initializes the temperature sensor driver, including setting up the appropriate ADC channel.
* This must be called before any other temperature sensor routines.
*
* \pre The ADC itself (not the ADC channel) must be configured separately before calling the
* temperature sensor functions.
*/
static inline void Temperature_Init(void) ATTR_ALWAYS_INLINE;
static inline void Temperature_Init(void)
{
ADC_SetupChannel(TEMP_ADC_CHANNEL);
}
/* Function Prototypes: */
/** Performs a complete ADC on the temperature sensor channel, and converts the result into a

@ -88,6 +88,44 @@
#define DATAFLASH_PAGES 8192
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The AVR's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void)
{
DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
}
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Dataflash_GetSelectedChip(void)
{
return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
}
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
static inline void Dataflash_SelectChip(const uint8_t ChipMask)
{
DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask);
}
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
static inline void Dataflash_DeselectChip(void)
{
Dataflash_SelectChip(DATAFLASH_NO_CHIP);
}
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
@ -110,6 +148,28 @@
Dataflash_SelectChip(DATAFLASH_CHIP1);
}
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void)
{
uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
Dataflash_DeselectChip();
Dataflash_SelectChip(SelectedChipMask);
}
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void)
{
Dataflash_ToggleSelectedChipCS();
Dataflash_SendByte(DF_CMD_GETSTATUS);
while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
Dataflash_ToggleSelectedChipCS();
}
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-byte address.
*

@ -91,6 +91,44 @@
#endif
/* Inline Functions: */
/** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
* The AVR's SPI driver MUST be initialized before any of the dataflash commands are used.
*/
static inline void Dataflash_Init(void)
{
DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
}
/** Determines the currently selected dataflash chip.
*
* \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
* or a DATAFLASH_CHIPn mask (where n is the chip number).
*/
static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t Dataflash_GetSelectedChip(void)
{
return (DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
}
/** Selects the given dataflash chip.
*
* \param[in] ChipMask Mask of the Dataflash IC to select, in the form of DATAFLASH_CHIPn mask (where n is
* the chip number).
*/
static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
static inline void Dataflash_SelectChip(const uint8_t ChipMask)
{
DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT & ~DATAFLASH_CHIPCS_MASK) | ChipMask);
}
/** Deselects the current dataflash chip, so that no dataflash is selected. */
static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
static inline void Dataflash_DeselectChip(void)
{
Dataflash_SelectChip(DATAFLASH_NO_CHIP);
}
/** Selects a dataflash IC from the given page number, which should range from 0 to
* ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
* dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
@ -109,6 +147,28 @@
Dataflash_SelectChip(DATAFLASH_CHIP1);
}
/** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
* a new command.
*/
static inline void Dataflash_ToggleSelectedChipCS(void)
{
uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
Dataflash_DeselectChip();
Dataflash_SelectChip(SelectedChipMask);
}
/** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
* memory page program or main memory to buffer transfer.
*/
static inline void Dataflash_WaitWhileBusy(void)
{
Dataflash_ToggleSelectedChipCS();
Dataflash_SendByte(DF_CMD_GETSTATUS);
while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
Dataflash_ToggleSelectedChipCS();
}
/** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
* dataflash commands which require a complete 24-byte address.

@ -196,52 +196,6 @@
#define ADC_INT_TEMP_SENS ((1 << 8) | (0x07 << MUX0))
#endif
//@}
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Initializes the ADC, ready for conversions. This must be called before any other ADC operations.
* The "mode" parameter should be a mask comprised of a conversion mode (free running or single) and
* prescaler masks.
*
* \param[in] Mode Mask of ADC settings, including adjustment, prescale, mode and reference.
*/
static inline void ADC_Init(uint8_t Mode);
/** Turns off the ADC. If this is called, any further ADC operations will require a call to
* \ref ADC_Init() before the ADC can be used again.
*/
static inline void ADC_ShutDown(void);
/** Indicates if the ADC is currently enabled.
*
* \return Boolean true if the ADC subsystem is currently enabled, false otherwise.
*/
static inline bool ADC_GetStatus(void);
/** Indicates if the current ADC conversion is completed, or still in progress.
*
* \return Boolean false if the reading is still taking place, or true if the conversion is
* complete and ready to be read out with \ref ADC_GetResult().
*/
static inline bool ADC_IsReadingComplete(void);
/** Retrieves the conversion value of the last completed ADC conversion and clears the reading
* completion flag.
*
* \return The result of the last ADC conversion as an unsigned value.
*/
static inline uint16_t ADC_GetResult(void);
#else
#define ADC_Init(mode) MACROS{ ADCSRA = ((1 << ADEN) | mode); }MACROE
#define ADC_ShutDown() MACROS{ ADCSRA = 0; }MACROE
#define ADC_GetStatus() ((ADCSRA & (1 << ADEN)) ? true : false)
#define ADC_IsReadingComplete() ((ADCSRA & (1 << ADIF)) ? true : false)
#define ADC_GetResult() (ADCSRA |= (1 << ADIF), ADC)
#endif
/* Inline Functions: */
/** Configures the given ADC channel, ready for ADC conversions. This function sets the
@ -354,6 +308,29 @@
ADCSRA |= (1 << ADSC);
}
/** Indicates if the current ADC conversion is completed, or still in progress.
*
* \return Boolean false if the reading is still taking place, or true if the conversion is
* complete and ready to be read out with \ref ADC_GetResult().
*/
static inline bool ADC_IsReadingComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool ADC_IsReadingComplete(void)
{
return ((ADCSRA & (1 << ADIF)) ? true : false);
}
/** Retrieves the conversion value of the last completed ADC conversion and clears the reading
* completion flag.
*
* \return The result of the last ADC conversion as an unsigned value.
*/
static inline uint16_t ADC_GetResult(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t ADC_GetResult(void)
{
ADCSRA |= (1 << ADIF);
return ADC;
}
/** Performs a complete single reading from channel, including a polling spin-loop to wait for the
* conversion to complete, and the returning of the converted value.
*
@ -373,6 +350,37 @@
return ADC_GetResult();
}
/** Initializes the ADC, ready for conversions. This must be called before any other ADC operations.
* The "mode" parameter should be a mask comprised of a conversion mode (free running or single) and
* prescaler masks.
*
* \param[in] Mode Mask of ADC settings, including adjustment, prescale, mode and reference.
*/
static inline void ADC_Init(uint8_t Mode) ATTR_ALWAYS_INLINE;
static inline void ADC_Init(uint8_t Mode)
{
ADCSRA = ((1 << ADEN) | Mode);
}
/** Turns off the ADC. If this is called, any further ADC operations will require a call to
* \ref ADC_Init() before the ADC can be used again.
*/
static inline void ADC_ShutDown(void) ATTR_ALWAYS_INLINE;
static inline void ADC_ShutDown(void)
{
ADCSRA = 0;
}
/** Indicates if the ADC is currently enabled.
*
* \return Boolean true if the ADC subsystem is currently enabled, false otherwise.
*/
static inline bool ADC_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool ADC_GetStatus(void)
{
return ((ADCSRA & (1 << ADEN)) ? true : false);
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}

@ -70,24 +70,27 @@
#endif
/* Public Interface - May be used in end-application: */
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Initializes the TWI hardware into master mode, ready for data transmission and reception. This must be
* before any other TWI operations.
*/
static inline void TWI_Init(void);
/** Turns off the TWI driver hardware. If this is called, any further TWI operations will require a call to
* \ref TWI_Init() before the TWI can be used again.
*/
static inline void TWI_ShutDown(void);
#else
#define TWI_Init() MACROS{ TWCR |= (1 << TWEN); }MACROE
#define TWI_ShutDown() MACROS{ TWCR &= ~(1 << TWEN); }MACROE
#endif
/* Inline Functions: */
/** Initializes the TWI hardware into master mode, ready for data transmission and reception. This must be
* before any other TWI operations.
*/
static inline void TWI_Init(void) ATTR_ALWAYS_INLINE;
static inline void TWI_Init(void)
{
TWCR |= (1 << TWEN);
}
/** Turns off the TWI driver hardware. If this is called, any further TWI operations will require a call to
* \ref TWI_Init() before the TWI can be used again.
*/
static inline void TWI_ShutDown(void) ATTR_ALWAYS_INLINE;
static inline void TWI_ShutDown(void)
{
TWCR &= ~(1 << TWEN);
}
/** Sends a TWI STOP onto the TWI bus, terminating communication with the currently addressed device. */
static inline void TWI_StopTransmission(void) ATTR_ALWAYS_INLINE;
static inline void TWI_StopTransmission(void)
{
TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN));

@ -76,17 +76,6 @@
*/
#define SERIAL_2X_UBBRVAL(baud) ((((F_CPU / 8) + (baud / 2)) / (baud)) - 1)
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Indicates whether a character has been received through the USART.
*
* \return Boolean true if a character has been received, false otherwise.
*/
static inline bool Serial_IsCharReceived(void);
#else
#define Serial_IsCharReceived() ((UCSR1A & (1 << RXC1)) ? true : false)
#endif
/* Function Prototypes: */
/** Transmits a given string located in program space (FLASH) through the USART.
*
@ -132,11 +121,22 @@
UBRR1 = 0;
}
/** Indicates whether a character has been received through the USART.
*
* \return Boolean true if a character has been received, false otherwise.
*/
static inline bool Serial_IsCharReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Serial_IsCharReceived(void)
{
return ((UCSR1A & (1 << RXC1)) ? true : false);
}
/** Transmits a given byte through the USART.
*
* \param[in] DataByte Byte to transmit through the USART.
*/
static inline void Serial_TxByte(const char DataByte) ATTR_ALWAYS_INLINE;
static inline void Serial_TxByte(const char DataByte)
{
while (!(UCSR1A & (1 << UDRE1)));
@ -147,6 +147,7 @@
*
* \return Byte received from the USART.
*/
static inline char Serial_RxByte(void) ATTR_ALWAYS_INLINE;
static inline char Serial_RxByte(void)
{
while (!(UCSR1A & (1 << RXC1)));

@ -50,11 +50,13 @@
#define __USBDEVICE_H__
/* Includes: */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "../../../Common/Common.h"
#include "../HighLevel/StdDescriptors.h"
#include "USBInterrupt.h"
#include "Endpoint.h"
/* Preprocessor Checks: */
@ -107,24 +109,6 @@
* \see \ref Group_Descriptors for more information on the RMWAKEUP feature and device descriptors.
*/
void USB_Device_SendRemoteWakeup(void);
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Enables the device mode Start Of Frame events. When enabled, this causes the
* \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
* at the start of each USB frame when enumerated in device mode.
*/
static inline bool USB_Device_EnableSOFEvents(void);
/** Disables the device mode Start Of Frame events. When disabled, this stop the firing of the
* \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode.
*/
static inline bool USB_Device_DisableSOFEvents(void);
#else
#define USB_Device_EnableSOFEvents() MACROS{ USB_INT_Enable(USB_INT_SOFI); }MACROE
#define USB_Device_DisableSOFEvents() MACROS{ USB_INT_Disable(USB_INT_SOFI); }MACROE
#endif
/* Type Defines: */
enum USB_Device_States_t
@ -155,6 +139,26 @@
*/
};
/* Inline Functions: */
/** Enables the device mode Start Of Frame events. When enabled, this causes the
* \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
* at the start of each USB frame when enumerated in device mode.
*/
static inline void USB_Device_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_EnableSOFEvents(void)
{
USB_INT_Enable(USB_INT_SOFI);
}
/** Disables the device mode Start Of Frame events. When disabled, this stop the firing of the
* \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode.
*/
static inline void USB_Device_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_DisableSOFEvents(void)
{
USB_INT_Disable(USB_INT_SOFI);
}
/* Function Prototypes: */
/** Function to retrieve a given descriptor's size and memory location from the given descriptor type value,
* index and language ID. This function MUST be overridden in the user application (added with full, identical
@ -191,12 +195,26 @@
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define USB_Device_SetLowSpeed() MACROS{ UDCON |= (1 << LSM); }MACROE
#define USB_Device_SetFullSpeed() MACROS{ UDCON &= ~(1 << LSM); }MACROE
/* Inline Functions: */
#if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetLowSpeed(void)
{
UDCON |= (1 << LSM);
}
#define USB_Device_SetDeviceAddress(addr) MACROS{ UDADDR = ((1 << ADDEN) | (addr & 0x7F)); }MACROE
static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetFullSpeed(void)
{
UDCON &= ~(1 << LSM);
}
#endif
static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Device_SetDeviceAddress(const uint8_t Address)
{
UDADDR = ((1 << ADDEN) | (Address & 0x7F));
}
#endif
#endif

@ -83,6 +83,7 @@
#include "../../../Common/Common.h"
#include "../HighLevel/USBTask.h"
#include "USBInterrupt.h"
#if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__)
#include "../HighLevel/StreamCallbacks.h"
@ -149,7 +150,7 @@
/** Endpoint bank size mask, for masking against endpoint addresses to retrieve the endpoint's
* bank size in the device.
*/
#define ENDPOINT_EPSIZE_MASK 0x7FF
#define ENDPOINT_EPSIZE_MASK 0x7F
/** Maximum size in bytes of a given endpoint.
*
@ -176,258 +177,6 @@
#else
#define ENDPOINT_TOTAL_ENDPOINTS 1
#endif
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
*
* \note The return width of this function may differ, depending on the maximum endpoint bank size
* of the selected AVR model.
*
* \ingroup Group_EndpointRW
*
* \return Total number of bytes in the currently selected Endpoint's FIFO buffer.
*/
static inline uint16_t Endpoint_BytesInEndpoint(void);
/** Get the endpoint address of the currently selected endpoint. This is typically used to save
* the currently selected endpoint number so that it can be restored after another endpoint has
* been manipulated.
*
* \return Index of the currently selected endpoint.
*/
static inline uint8_t Endpoint_GetCurrentEndpoint(void);
/** Selects the given endpoint number. If the address from the device descriptors is used, the
* value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint
* number (and discarding the endpoint direction bit).
*
* Any endpoint operations which do not require the endpoint number to be indicated will operate on
* the currently selected endpoint.
*
* \param[in] EndpointNumber Endpoint number to select.
*/
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber);
/** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
* In and Out pointers to the bank's contents.
*
* \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset.
*/
static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber);
/** Enables the currently selected endpoint so that data can be sent and received through it to
* and from a host.
*
* \note Endpoints must first be configured properly via \ref Endpoint_ConfigureEndpoint().
*/
static inline void Endpoint_EnableEndpoint(void);
/** Disables the currently selected endpoint so that data cannot be sent and received through it
* to and from a host.
*/
static inline void Endpoint_DisableEndpoint(void);
/** Determines if the currently selected endpoint is enabled, but not necessarily configured.
*
* \return Boolean True if the currently selected endpoint is enabled, false otherwise.
*/
static inline bool Endpoint_IsEnabled(void);
/** Determines if the currently selected endpoint may be read from (if data is waiting in the endpoint
* bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an IN
* direction). This function will return false if an error has occurred in the endpoint, if the endpoint
* is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN
* direction and the endpoint bank is full.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if the currently selected endpoint may be read from or written to, depending on its direction.
*/
static inline bool Endpoint_IsReadWriteAllowed(void);
/** Determines if the currently selected endpoint is configured.
*
* \return Boolean true if the currently selected endpoint has been configured, false otherwise.
*/
static inline bool Endpoint_IsConfigured(void);
/** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
* interrupt duration has elapsed. Which endpoints have interrupted can be determined by
* masking the return value against (1 << {Endpoint Number}).
*
* \return Mask whose bits indicate which endpoints have interrupted.
*/
static inline uint8_t Endpoint_GetEndpointInterrupts(void);
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
* endpoints).
*
* \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested.
*
* \return Boolean true if the specified endpoint has interrupted, false otherwise.
*/
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber);
/** Determines if the selected IN endpoint is ready for a new packet.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if the current endpoint is ready for an IN packet, false otherwise.
*/
static inline bool Endpoint_IsINReady(void);
/** Determines if the selected OUT endpoint has received new packet.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if current endpoint is has received an OUT packet, false otherwise.
*/
static inline bool Endpoint_IsOUTReceived(void);
/** Determines if the current CONTROL type endpoint has received a SETUP packet.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if the selected endpoint has received a SETUP packet, false otherwise.
*/
static inline bool Endpoint_IsSETUPReceived(void);
/** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
* endpoint for the next packet.
*
* \ingroup Group_EndpointPacketManagement
*
* \note This is not applicable for non CONTROL type endpoints.
*/
static inline void Endpoint_ClearSETUP(void);
/** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the
* next packet and switching to the alternative endpoint bank if double banked.
*
* \ingroup Group_EndpointPacketManagement
*/
static inline void Endpoint_ClearIN(void);
/** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint
* for the next packet and switching to the alternative endpoint bank if double banked.
*
* \ingroup Group_EndpointPacketManagement
*/
static inline void Endpoint_ClearOUT(void);
/** Stalls the current endpoint, indicating to the host that a logical problem occurred with the
* indicated endpoint and that the current transfer sequence should be aborted. This provides a
* way for devices to indicate invalid commands to the host so that the current transfer can be
* aborted and the host can begin its own recovery sequence.
*
* The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro
* is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
* endpoint.
*
* \ingroup Group_EndpointPacketManagement
*/
static inline void Endpoint_StallTransaction(void);
/** Clears the STALL condition on the currently selected endpoint.
*
* \ingroup Group_EndpointPacketManagement
*/
static inline void Endpoint_ClearStall(void);
/** Determines if the currently selected endpoint is stalled, false otherwise.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if the currently selected endpoint is stalled, false otherwise.
*/
static inline bool Endpoint_IsStalled(void);
/** Resets the data toggle of the currently selected endpoint. */
static inline void Endpoint_ResetDataToggle(void);
/** Determines the currently selected endpoint's direction.
*
* \return The currently selected endpoint's direction, as a ENDPOINT_DIR_* mask.
*/
static inline uint8_t Endpoint_GetEndpointDirection(void);
/** Sets the direction of the currently selected endpoint.
*
* \param[in] DirectionMask New endpoint direction, as a ENDPOINT_DIR_* mask.
*/
static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask);
#else
#if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
#define Endpoint_BytesInEndpoint() UEBCX
#elif defined(USB_SERIES_4_AVR)
#define Endpoint_BytesInEndpoint() (((uint16_t)UEBCHX << 8) | UEBCLX)
#elif defined(USB_SERIES_2_AVR)
#define Endpoint_BytesInEndpoint() UEBCLX
#endif
#if !defined(CONTROL_ONLY_DEVICE)
#define Endpoint_GetCurrentEndpoint() (UENUM & ENDPOINT_EPNUM_MASK)
#else
#define Endpoint_GetCurrentEndpoint() ENDPOINT_CONTROLEP
#endif
#if !defined(CONTROL_ONLY_DEVICE)
#define Endpoint_SelectEndpoint(epnum) MACROS{ UENUM = (epnum); }MACROE
#else
#define Endpoint_SelectEndpoint(epnum) (void)(epnum)
#endif
#define Endpoint_ResetFIFO(epnum) MACROS{ UERST = (1 << (epnum)); UERST = 0; }MACROE
#define Endpoint_EnableEndpoint() MACROS{ UECONX |= (1 << EPEN); }MACROE
#define Endpoint_DisableEndpoint() MACROS{ UECONX &= ~(1 << EPEN); }MACROE
#define Endpoint_IsEnabled() ((UECONX & (1 << EPEN)) ? true : false)
#if !defined(CONTROL_ONLY_DEVICE)
#define Endpoint_IsReadWriteAllowed() ((UEINTX & (1 << RWAL)) ? true : false)
#endif
#define Endpoint_IsConfigured() ((UESTA0X & (1 << CFGOK)) ? true : false)
#define Endpoint_GetEndpointInterrupts() UEINT
#define Endpoint_HasEndpointInterrupted(n) ((UEINT & (1 << (n))) ? true : false)
#define Endpoint_IsINReady() ((UEINTX & (1 << TXINI)) ? true : false)
#define Endpoint_IsOUTReceived() ((UEINTX & (1 << RXOUTI)) ? true : false)
#define Endpoint_IsSETUPReceived() ((UEINTX & (1 << RXSTPI)) ? true : false)
#define Endpoint_ClearSETUP() MACROS{ UEINTX &= ~(1 << RXSTPI); }MACROE
#if !defined(CONTROL_ONLY_DEVICE)
#define Endpoint_ClearIN() MACROS{ UEINTX &= ~((1 << TXINI) | (1 << FIFOCON)); }MACROE
#else
#define Endpoint_ClearIN() MACROS{ UEINTX &= ~(1 << TXINI); }MACROE
#endif
#if !defined(CONTROL_ONLY_DEVICE)
#define Endpoint_ClearOUT() MACROS{ UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON)); }MACROE
#else
#define Endpoint_ClearOUT() MACROS{ UEINTX &= ~(1 << RXOUTI); }MACROE
#endif
#define Endpoint_StallTransaction() MACROS{ UECONX |= (1 << STALLRQ); }MACROE
#define Endpoint_ClearStall() MACROS{ UECONX |= (1 << STALLRQC); }MACROE
#define Endpoint_IsStalled() ((UECONX & (1 << STALLRQ)) ? true : false)
#define Endpoint_ResetDataToggle() MACROS{ UECONX |= (1 << RSTDT); }MACROE
#define Endpoint_GetEndpointDirection() (UECFG0X & ENDPOINT_DIR_IN)
#define Endpoint_SetEndpointDirection(dir) MACROS{ UECFG0X = ((UECFG0X & ~ENDPOINT_DIR_IN) | (dir)); }MACROE
#endif
/* Enums: */
/** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
@ -497,6 +246,298 @@
};
/* Inline Functions: */
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
*
* \note The return width of this function may differ, depending on the maximum endpoint bank size
* of the selected AVR model.
*
* \ingroup Group_EndpointRW
*
* \return Total number of bytes in the currently selected Endpoint's FIFO buffer.
*/
static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Endpoint_BytesInEndpoint(void)
{
#if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
return UEBCX;
#elif defined(USB_SERIES_4_AVR)
return (((uint16_t)UEBCHX << 8) | UEBCLX);
#elif defined(USB_SERIES_2_AVR)
return UEBCLX;
#endif
}
/** Get the endpoint address of the currently selected endpoint. This is typically used to save
* the currently selected endpoint number so that it can be restored after another endpoint has
* been manipulated.
*
* \return Index of the currently selected endpoint.
*/
static inline uint8_t Endpoint_GetCurrentEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_GetCurrentEndpoint(void)
{
#if !defined(CONTROL_ONLY_DEVICE)
return (UENUM & ENDPOINT_EPNUM_MASK);
#else
return ENDPOINT_CONTROLEP;
#endif
}
/** Selects the given endpoint number. If the address from the device descriptors is used, the
* value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint
* number (and discarding the endpoint direction bit).
*
* Any endpoint operations which do not require the endpoint number to be indicated will operate on
* the currently selected endpoint.
*
* \param[in] EndpointNumber Endpoint number to select.
*/
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber)
{
#if !defined(CONTROL_ONLY_DEVICE)
UENUM = EndpointNumber;
#endif
}
/** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
* In and Out pointers to the bank's contents.
*
* \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset.
*/
static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber)
{
UERST = (1 << EndpointNumber);
UERST = 0;
}
/** Enables the currently selected endpoint so that data can be sent and received through it to
* and from a host.
*
* \note Endpoints must first be configured properly via \ref Endpoint_ConfigureEndpoint().
*/
static inline void Endpoint_EnableEndpoint(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_EnableEndpoint(void)
{
UECONX |= (1 << EPEN);
}
/** Disables the currently selected endpoint so that data cannot be sent and received through it
* to and from a host.
*/
static inline void Endpoint_DisableEndpoint(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_DisableEndpoint(void)
{
UECONX &= ~(1 << EPEN);
}
/** Determines if the currently selected endpoint is enabled, but not necessarily configured.
*
* \return Boolean True if the currently selected endpoint is enabled, false otherwise.
*/
static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsEnabled(void)
{
return ((UECONX & (1 << EPEN)) ? true : false);
}
/** Determines if the currently selected endpoint may be read from (if data is waiting in the endpoint
* bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an IN
* direction). This function will return false if an error has occurred in the endpoint, if the endpoint
* is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN
* direction and the endpoint bank is full.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if the currently selected endpoint may be read from or written to, depending on its direction.
*/
static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsReadWriteAllowed(void)
{
return ((UEINTX & (1 << RWAL)) ? true : false);
}
/** Determines if the currently selected endpoint is configured.
*
* \return Boolean true if the currently selected endpoint has been configured, false otherwise.
*/
static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsConfigured(void)
{
return ((UESTA0X & (1 << CFGOK)) ? true : false);
}
/** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
* interrupt duration has elapsed. Which endpoints have interrupted can be determined by
* masking the return value against (1 << {Endpoint Number}).
*
* \return Mask whose bits indicate which endpoints have interrupted.
*/
static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_GetEndpointInterrupts(void)
{
return UEINT;
}
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
* endpoints).
*
* \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested.
*
* \return Boolean true if the specified endpoint has interrupted, false otherwise.
*/
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber)
{
return ((UEINT & (1 << EndpointNumber)) ? true : false);
}
/** Determines if the selected IN endpoint is ready for a new packet.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if the current endpoint is ready for an IN packet, false otherwise.
*/
static inline bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsINReady(void)
{
return ((UEINTX & (1 << TXINI)) ? true : false);
}
/** Determines if the selected OUT endpoint has received new packet.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if current endpoint is has received an OUT packet, false otherwise.
*/
static inline bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsOUTReceived(void)
{
return ((UEINTX & (1 << RXOUTI)) ? true : false);
}
/** Determines if the current CONTROL type endpoint has received a SETUP packet.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if the selected endpoint has received a SETUP packet, false otherwise.
*/
static inline bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsSETUPReceived(void)
{
return ((UEINTX & (1 << RXSTPI)) ? true : false);
}
/** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
* endpoint for the next packet.
*
* \ingroup Group_EndpointPacketManagement
*
* \note This is not applicable for non CONTROL type endpoints.
*/
static inline void Endpoint_ClearSETUP(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearSETUP(void)
{
UEINTX &= ~(1 << RXSTPI);
}
/** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the
* next packet and switching to the alternative endpoint bank if double banked.
*
* \ingroup Group_EndpointPacketManagement
*/
static inline void Endpoint_ClearIN(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearIN(void)
{
#if !defined(CONTROL_ONLY_DEVICE)
UEINTX &= ~((1 << TXINI) | (1 << FIFOCON));
#else
UEINTX &= ~(1 << TXINI);
#endif
}
/** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint
* for the next packet and switching to the alternative endpoint bank if double banked.
*
* \ingroup Group_EndpointPacketManagement
*/
static inline void Endpoint_ClearOUT(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearOUT(void)
{
#if !defined(CONTROL_ONLY_DEVICE)
UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON));
#else
UEINTX &= ~(1 << RXOUTI);
#endif
}
/** Stalls the current endpoint, indicating to the host that a logical problem occurred with the
* indicated endpoint and that the current transfer sequence should be aborted. This provides a
* way for devices to indicate invalid commands to the host so that the current transfer can be
* aborted and the host can begin its own recovery sequence.
*
* The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro
* is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
* endpoint.
*
* \ingroup Group_EndpointPacketManagement
*/
static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_StallTransaction(void)
{
UECONX |= (1 << STALLRQ);
}
/** Clears the STALL condition on the currently selected endpoint.
*
* \ingroup Group_EndpointPacketManagement
*/
static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ClearStall(void)
{
UECONX |= (1 << STALLRQC);
}
/** Determines if the currently selected endpoint is stalled, false otherwise.
*
* \ingroup Group_EndpointPacketManagement
*
* \return Boolean true if the currently selected endpoint is stalled, false otherwise.
*/
static inline bool Endpoint_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Endpoint_IsStalled(void)
{
return ((UECONX & (1 << STALLRQ)) ? true : false);
}
/** Resets the data toggle of the currently selected endpoint. */
static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE;
static inline void Endpoint_ResetDataToggle(void)
{
UECONX |= (1 << RSTDT);
}
/** Determines the currently selected endpoint's direction.
*
* \return The currently selected endpoint's direction, as a ENDPOINT_DIR_* mask.
*/
static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_GetEndpointDirection(void)
{
return (UECFG0X & ENDPOINT_DIR_IN);
}
/** Sets the direction of the currently selected endpoint.
*
* \param[in] DirectionMask New endpoint direction, as a ENDPOINT_DIR_* mask.
*/
static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask) ATTR_ALWAYS_INLINE;
static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask)
{
UECFG0X = ((UECFG0X & ~ENDPOINT_DIR_IN) | DirectionMask);
}
/** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints.
*
* \ingroup Group_EndpointPrimitiveRW
@ -936,9 +977,9 @@
*
* \ingroup Group_EndpointStreamRW
*
* \param[out] Buffer Pointer to the destination data buffer to write to.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback.
* \param[out] Buffer Pointer to the destination data buffer to write to.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
@ -950,9 +991,9 @@
*
* \ingroup Group_EndpointStreamRW
*
* \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback.
* \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
@ -976,8 +1017,8 @@
* \ingroup Group_EndpointStreamRW
*
* \param[out] Buffer Pointer to the destination data buffer to write to.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
@ -989,9 +1030,9 @@
*
* \ingroup Group_EndpointStreamRW
*
* \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback.
* \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
* \param[in] Length Number of bytes to send via the currently selected endpoint.
* \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback.
*
* \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
*/
@ -1260,13 +1301,6 @@
Endpoint_BytesToEPSizeMask(Size) : \
Endpoint_BytesToEPSizeMaskDynamic(Size))))
/* Function Prototypes: */
void Endpoint_ClearEndpoints(void);
uint8_t Endpoint_BytesToEPSizeMaskDynamic(const uint16_t Size);
bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
const uint8_t UECFG0XData,
const uint8_t UECFG1XData);
/* Inline Functions: */
static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYS_INLINE;
static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
@ -1283,6 +1317,12 @@
return (MaskVal << EPSIZE0);
}
/* Function Prototypes: */
void Endpoint_ClearEndpoints(void);
uint8_t Endpoint_BytesToEPSizeMaskDynamic(const uint16_t Size);
bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
const uint8_t UECFG0XData,
const uint8_t UECFG1XData);
#endif
/* Disable C linkage for C++ Compilers: */

@ -100,148 +100,6 @@
*/
#define HOST_DEVICE_SETTLE_DELAY_MS 1500
#endif
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host.
* USB bus resets leave the default control pipe configured (if already configured).
*
* If the USB bus has been suspended prior to issuing a bus reset, the attached device will be
* woken up automatically and the bus resumed after the reset has been correctly issued.
*/
static inline void USB_Host_ResetBus(void);
/** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has
* completed.
*
* \return Boolean true if no bus reset is currently being sent, false otherwise.
*/
static inline void USB_Host_IsBusResetComplete(void);
/** Resumes USB communications with an attached and enumerated device, by resuming the transmission
* of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the
* host and attached device may occur.
*/
static inline void USB_Host_ResumeBus(void);
/** Suspends the USB bus, preventing any communications from occurring between the host and attached
* device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame
* messages to the device.
*/
static inline void USB_Host_SuspendBus(void);
/** Determines if the USB bus has been suspended via the use of the \ref USB_Host_SuspendBus() macro,
* false otherwise. While suspended, no USB communications can occur until the bus is resumed,
* except for the Remote Wakeup event from the device if supported.
*
* \return Boolean true if the bus is currently suspended, false otherwise.
*/
static inline bool USB_Host_IsBusSuspended(void);
/** Determines if the attached device is currently enumerated in Full Speed mode (12Mb/s), or
* false if the attached device is enumerated in Low Speed mode (1.5Mb/s).
*
* \return Boolean true if the attached device is enumerated in Full Speed mode, false otherwise.
*/
static inline bool USB_Host_IsDeviceFullSpeed(void);
/** Determines if the attached device is currently issuing a Remote Wakeup request, requesting
* that the host resume the USB bus and wake up the device, false otherwise.
*
* \return Boolean true if the attached device has sent a Remote Wakeup request, false otherwise.
*/
static inline bool USB_Host_IsRemoteWakeupSent(void);
/** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */
static inline void USB_Host_ClearRemoteWakeupSent(void);
/** Accepts a Remote Wakeup request from an attached device. This must be issued in response to
* a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to
* be resumed.
*/
static inline void USB_Host_ResumeFromWakeupRequest(void);
/** Determines if a resume from Remote Wakeup request is currently being sent to an attached
* device.
*
* \return Boolean true if no resume request is currently being sent, false otherwise.
*/
static inline bool USB_Host_IsResumeFromWakeupRequestSent(void);
#else
#define USB_Host_ResetBus() MACROS{ UHCON |= (1 << RESET); }MACROE
#define USB_Host_IsBusResetComplete() ((UHCON & (1 << RESET)) ? false : true)
#define USB_Host_ResumeBus() MACROS{ UHCON |= (1 << SOFEN); }MACROE
#define USB_Host_SuspendBus() MACROS{ UHCON &= ~(1 << SOFEN); }MACROE
#define USB_Host_IsBusSuspended() ((UHCON & (1 << SOFEN)) ? false : true)
#define USB_Host_IsDeviceFullSpeed() ((USBSTA & (1 << SPEED)) ? true : false)
#define USB_Host_IsRemoteWakeupSent() ((UHINT & (1 << RXRSMI)) ? true : false)
#define USB_Host_ClearRemoteWakeupSent() MACROS{ UHINT &= ~(1 << RXRSMI); }MACROE
#define USB_Host_ResumeFromWakeupRequest() MACROS{ UHCON |= (1 << RESUME); }MACROE
#define USB_Host_IsResumeFromWakeupRequestSent() ((UHCON & (1 << RESUME)) ? false : true)
#endif
/* Function Prototypes: */
/** Convenience function. This routine sends a SetConfiguration standard request to the attached
* device, with the given configuration index. This can be used to easily set the device
* configuration without creating and sending the request manually.
*
* \note After this routine returns, the control pipe will be selected.
*
* \param[in] ConfigNumber Configuration index to send to the device.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber);
/** Convenience function. This routine sends a GetDescriptor standard request to the attached
* device, requesting the device descriptor. This can be used to easily retrieve information
* about the device such as its VID, PID and power requirements.
*
* \note After this routine returns, the control pipe will be selected.
*
* \param[out] DeviceDescriptorPtr Pointer to the destination device descriptor structure where
* the read data is to be stored.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr);
/** Convenience function. This routine sends a GetDescriptor standard request to the attached
* device, requesting the string descriptor of the specified index. This can be used to easily
* retrieve string descriptors from the device by index, after the index is obtained from the
* Device or Configuration descriptors.
*
* \note After this routine returns, the control pipe will be selected.
*
* \param[in] Index Index of the string index to retrieve.
* \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is
* to be stored.
* \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index,
void* const Buffer,
const uint8_t BufferLength);
/** Clears a stall condition on the given pipe, via a ClearFeature request to the attached device.
*
* \note After this routine returns, the control pipe will be selected.
*
* \param[in] EndpointIndex Index of the endpoint to clear.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_ClearPipeStall(uint8_t EndpointIndex);
/* Enums: */
/** Enum for the various states of the USB Host state machine. Only some states are
@ -385,22 +243,226 @@
*/
};
/* Inline Functions: */
/** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host.
* USB bus resets leave the default control pipe configured (if already configured).
*
* If the USB bus has been suspended prior to issuing a bus reset, the attached device will be
* woken up automatically and the bus resumed after the reset has been correctly issued.
*/
static inline void USB_Host_ResetBus(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_ResetBus(void)
{
UHCON |= (1 << RESET);
}
/** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has
* completed.
*
* \return Boolean true if no bus reset is currently being sent, false otherwise.
*/
static inline bool USB_Host_IsBusResetComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsBusResetComplete(void)
{
return ((UHCON & (1 << RESET)) ? false : true);
}
/** Resumes USB communications with an attached and enumerated device, by resuming the transmission
* of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the
* host and attached device may occur.
*/
static inline void USB_Host_ResumeBus(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_ResumeBus(void)
{
UHCON |= (1 << SOFEN);
}
/** Suspends the USB bus, preventing any communications from occurring between the host and attached
* device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame
* messages to the device.
*/
static inline void USB_Host_SuspendBus(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_SuspendBus(void)
{
UHCON &= ~(1 << SOFEN);
}
/** Determines if the USB bus has been suspended via the use of the \ref USB_Host_SuspendBus() macro,
* false otherwise. While suspended, no USB communications can occur until the bus is resumed,
* except for the Remote Wakeup event from the device if supported.
*
* \return Boolean true if the bus is currently suspended, false otherwise.
*/
static inline bool USB_Host_IsBusSuspended(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsBusSuspended(void)
{
return ((UHCON & (1 << SOFEN)) ? false : true);
}
/** Determines if the attached device is currently enumerated in Full Speed mode (12Mb/s), or
* false if the attached device is enumerated in Low Speed mode (1.5Mb/s).
*
* \return Boolean true if the attached device is enumerated in Full Speed mode, false otherwise.
*/
static inline bool USB_Host_IsDeviceFullSpeed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsDeviceFullSpeed(void)
{
return ((USBSTA & (1 << SPEED)) ? true : false);
}
/** Determines if the attached device is currently issuing a Remote Wakeup request, requesting
* that the host resume the USB bus and wake up the device, false otherwise.
*
* \return Boolean true if the attached device has sent a Remote Wakeup request, false otherwise.
*/
static inline bool USB_Host_IsRemoteWakeupSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsRemoteWakeupSent(void)
{
return ((UHINT & (1 << RXRSMI)) ? true : false);
}
/** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */
static inline void USB_Host_ClearRemoteWakeupSent(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_ClearRemoteWakeupSent(void)
{
UHINT &= ~(1 << RXRSMI);
}
/** Accepts a Remote Wakeup request from an attached device. This must be issued in response to
* a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to
* be resumed.
*/
static inline void USB_Host_ResumeFromWakeupRequest(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_ResumeFromWakeupRequest(void)
{
UHCON |= (1 << RESUME);
}
/** Determines if a resume from Remote Wakeup request is currently being sent to an attached
* device.
*
* \return Boolean true if no resume request is currently being sent, false otherwise.
*/
static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_Host_IsResumeFromWakeupRequestSent(void)
{
return ((UHCON & (1 << RESUME)) ? false : true);
}
/* Function Prototypes: */
/** Convenience function. This routine sends a SetConfiguration standard request to the attached
* device, with the given configuration index. This can be used to easily set the device
* configuration without creating and sending the request manually.
*
* \note After this routine returns, the control pipe will be selected.
*
* \param[in] ConfigNumber Configuration index to send to the device.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber);
/** Convenience function. This routine sends a GetDescriptor standard request to the attached
* device, requesting the device descriptor. This can be used to easily retrieve information
* about the device such as its VID, PID and power requirements.
*
* \note After this routine returns, the control pipe will be selected.
*
* \param[out] DeviceDescriptorPtr Pointer to the destination device descriptor structure where
* the read data is to be stored.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr);
/** Convenience function. This routine sends a GetDescriptor standard request to the attached
* device, requesting the string descriptor of the specified index. This can be used to easily
* retrieve string descriptors from the device by index, after the index is obtained from the
* Device or Configuration descriptors.
*
* \note After this routine returns, the control pipe will be selected.
*
* \param[in] Index Index of the string index to retrieve.
* \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is
* to be stored.
* \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index,
void* const Buffer,
const uint8_t BufferLength);
/** Clears a stall condition on the given pipe, via a ClearFeature request to the attached device.
*
* \note After this routine returns, the control pipe will be selected.
*
* \param[in] EndpointIndex Index of the endpoint to clear.
*
* \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
*/
uint8_t USB_Host_ClearPipeStall(uint8_t EndpointIndex);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define USB_Host_HostMode_On() MACROS{ USBCON |= (1 << HOST); }MACROE
#define USB_Host_HostMode_Off() MACROS{ USBCON &= ~(1 << HOST); }MACROE
static inline void USB_Host_HostMode_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_HostMode_On(void)
{
USBCON |= (1 << HOST);
}
static inline void USB_Host_HostMode_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_HostMode_Off(void)
{
USBCON &= ~(1 << HOST);
}
static inline void USB_Host_VBUS_Auto_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_Enable(void)
{
OTGCON &= ~(1 << VBUSHWC);
UHWCON |= (1 << UVCONE);
}
static inline void USB_Host_VBUS_Manual_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_Enable(void)
{
OTGCON |= (1 << VBUSHWC);
UHWCON &= ~(1 << UVCONE);
DDRE |= (1 << 7);
}
#define USB_Host_VBUS_Auto_Enable() MACROS{ OTGCON &= ~(1 << VBUSHWC); UHWCON |= (1 << UVCONE); }MACROE
#define USB_Host_VBUS_Manual_Enable() MACROS{ OTGCON |= (1 << VBUSHWC); UHWCON &= ~(1 << UVCONE); DDRE |= (1 << 7); }MACROE
static inline void USB_Host_VBUS_Auto_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_On(void)
{
OTGCON |= (1 << VBUSREQ);
}
#define USB_Host_VBUS_Auto_On() MACROS{ OTGCON |= (1 << VBUSREQ); }MACROE
#define USB_Host_VBUS_Manual_On() MACROS{ PORTE |= (1 << 7); }MACROE
static inline void USB_Host_VBUS_Manual_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_On(void)
{
PORTE |= (1 << 7);
}
static inline void USB_Host_VBUS_Auto_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Auto_Off(void)
{
OTGCON |= (1 << VBUSRQC);
}
#define USB_Host_VBUS_Auto_Off() MACROS{ OTGCON |= (1 << VBUSRQC); }MACROE
#define USB_Host_VBUS_Manual_Off() MACROS{ PORTE &= ~(1 << 7); }MACROE
static inline void USB_Host_VBUS_Manual_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_Host_VBUS_Manual_Off(void)
{
PORTE &= ~(1 << 7);
}
#define USB_Host_SetDeviceAddress(addr) MACROS{ UHADDR = ((addr) & 0x7F); }MACROE
static inline void USB_Host_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
static inline void USB_Host_SetDeviceAddress(const uint8_t Address)
{
UHADDR = (Address & 0x7F);
}
/* Enums: */
enum USB_Host_WaitMSErrorCodes_t

@ -76,66 +76,78 @@
*/
#define USB_OTG_STP_DATA 0
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Initiate a Host Negotiation Protocol request. This indicates to the other connected device
* that the device wishes to change device/host roles.
*/
static inline void USB_OTG_Device_RequestHNP(void);
/** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other
* connected device.
*/
static inline void USB_OTG_Device_CancelHNPRequest(void);
/** Determines if the device is currently sending a HNP to an attached host.
*
* \return Boolean true if currently sending a HNP to the other connected device, false otherwise
*/
static inline bool USB_OTG_Device_IsSendingHNP(void);
/** Initiates a Session Request Protocol request. Most OTG devices turn off VBUS when the USB
* interface is not in use, to conserve power. Sending a SRP to a USB OTG device running in
* host mode indicates that VBUS should be applied and a session started.
*
* There are two different methods of sending a SRP - either pulses on the VBUS line, or by
* pulsing the Data + line via the internal pull-up resistor.
*
* \param[in] SRPTypeMask Mask indicating the type of SRP to use, either \ref USB_OTG_SRP_VBUS or
* \ref USB_OTG_STP_DATA.
*/
static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask);
/** Accepts a HNP from a connected device, indicating that both devices should exchange
* device/host roles.
*/
static inline void USB_OTG_Host_AcceptHNP(void);
/** Rejects a HNP from a connected device, indicating that both devices should remain in their
* current device/host roles.
*/
static inline void USB_OTG_Host_RejectHNP(void);
/** Indicates if the connected device is not currently sending a HNP request.
*
* \return Boolean true if a HNP is currently being issued by the connected device, false otherwise.
*/
static inline bool USB_OTG_Host_IsHNPReceived(void);
#else
#define USB_OTG_Device_RequestHNP() MACROS{ OTGCON |= (1 << HNPREQ); }MACROE
#define USB_OTG_Device_CancelHNPRequest() MACROS{ OTGCON &= ~(1 << HNPREQ); }MACROE
#define USB_OTG_Device_IsSendingHNP() ((OTGCON & (1 << HNPREQ)) ? true : false)
#define USB_OTG_Device_InitiateSRP(type) MACROS{ OTGCON = ((OTGCON & ~(1 << SRPSEL)) | ((type) | (1 << SRPREQ))); }MACROE
#define USB_OTG_Host_AcceptHNP() MACROS{ OTGCON |= (1 << HNPREQ); }MACROE
/* Inline Functions: */
/** Initiate a Host Negotiation Protocol request. This indicates to the other connected device
* that the device wishes to change device/host roles.
*/
static inline void USB_OTG_Device_RequestHNP(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Device_RequestHNP(void)
{
OTGCON |= (1 << HNPREQ);
}
/** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other
* connected device.
*/
static inline void USB_OTG_Device_CancelHNPRequest(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Device_CancelHNPRequest(void)
{
OTGCON &= ~(1 << HNPREQ);
}
/** Determines if the device is currently sending a HNP to an attached host.
*
* \return Boolean true if currently sending a HNP to the other connected device, false otherwise
*/
static inline bool USB_OTG_Device_IsSendingHNP(void) ATTR_ALWAYS_INLINE;
static inline bool USB_OTG_Device_IsSendingHNP(void)
{
return ((OTGCON & (1 << HNPREQ)) ? true : false);
}
/** Initiates a Session Request Protocol request. Most OTG devices turn off VBUS when the USB
* interface is not in use, to conserve power. Sending a SRP to a USB OTG device running in
* host mode indicates that VBUS should be applied and a session started.
*
* There are two different methods of sending a SRP - either pulses on the VBUS line, or by
* pulsing the Data + line via the internal pull-up resistor.
*
* \param[in] SRPTypeMask Mask indicating the type of SRP to use, either \ref USB_OTG_SRP_VBUS or
* \ref USB_OTG_STP_DATA.
*/
static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask)
{
OTGCON = ((OTGCON & ~(1 << SRPSEL)) | (SRPTypeMask | (1 << SRPREQ)));
}
#define USB_OTG_Host_RejectHNP() MACROS{ OTGCON &= ~(1 << HNPREQ); }MACROE
#define USB_OTG_Host_IsHNPReceived() ((OTGCON & (1 << HNPREQ)) ? true : false)
#endif
/** Accepts a HNP from a connected device, indicating that both devices should exchange
* device/host roles.
*/
static inline void USB_OTG_Host_AcceptHNP(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Host_AcceptHNP(void)
{
OTGCON |= (1 << HNPREQ);
}
/** Rejects a HNP from a connected device, indicating that both devices should remain in their
* current device/host roles.
*/
static inline void USB_OTG_Host_RejectHNP(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTG_Host_RejectHNP(void)
{
OTGCON &= ~(1 << HNPREQ);
}
/** Indicates if the connected device is not currently sending a HNP request.
*
* \return Boolean true if a HNP is currently being issued by the connected device, false otherwise.
*/
static inline bool USB_OTG_Host_IsHNPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_OTG_Host_IsHNPReceived(void)
{
return ((OTGCON & (1 << HNPREQ)) ? true : false);
}
#endif

@ -105,6 +105,14 @@
#if !defined(__INCLUDE_FROM_USB_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#if !defined(ENDPOINT_CONTROLEP) && !defined(__DOXYGEN__)
#define ENDPOINT_CONTROLEP 0
#endif
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
@ -195,319 +203,6 @@
*/
#define PIPE_EPDIR_MASK 0x80
/* Pseudo-Function Macros: */
#if defined(__DOXYGEN__)
/** Indicates the number of bytes currently stored in the current pipes's selected bank.
*
* \note The return width of this function may differ, depending on the maximum pipe bank size
* of the selected AVR model.
*
* \ingroup Group_PipeRW
*
* \return Total number of bytes in the currently selected Pipe's FIFO buffer.
*/
static inline uint16_t Pipe_BytesInPipe(void);
/** Returns the pipe address of the currently selected pipe. This is typically used to save the
* currently selected pipe number so that it can be restored after another pipe has been manipulated.
*
* \return Index of the currently selected pipe.
*/
static inline uint8_t Pipe_GetCurrentPipe(void);
/** Selects the given pipe number. Any pipe operations which do not require the pipe number to be
* indicated will operate on the currently selected pipe.
*
* \param[in] PipeNumber Index of the pipe to select.
*/
static inline void Pipe_SelectPipe(uint8_t PipeNumber);
/** Resets the desired pipe, including the pipe banks and flags.
*
* \param[in] PipeNumber Index of the pipe to reset.
*/
static inline void Pipe_ResetPipe(uint8_t PipeNumber);
/** Enables the currently selected pipe so that data can be sent and received through it to and from
* an attached device.
*
* \pre The currently selected pipe must first be configured properly via \ref Pipe_ConfigurePipe().
*/
static inline void Pipe_EnablePipe(void);
/** Disables the currently selected pipe so that data cannot be sent and received through it to and
* from an attached device.
*/
static inline void Pipe_DisablePipe(void);
/** Determines if the currently selected pipe is enabled, but not necessarily configured.
*
* \return Boolean True if the currently selected pipe is enabled, false otherwise.
*/
static inline bool Pipe_IsEnabled(void);
/** Gets the current pipe token, indicating the pipe's data direction and type.
*
* \return The current pipe token, as a PIPE_TOKEN_* mask.
*/
static inline uint8_t Pipe_GetPipeToken(void);
/** Sets the token for the currently selected pipe to one of the tokens specified by the PIPE_TOKEN_*
* masks. This can be used on CONTROL type pipes, to allow for bidirectional transfer of data during
* control requests, or on regular pipes to allow for half-duplex bidirectional data transfer to devices
* which have two endpoints of opposite direction sharing the same endpoint address within the device.
*
* \param[in] Token New pipe token to set the selected pipe to, as a PIPE_TOKEN_* mask.
*/
static inline void Pipe_SetPipeToken(uint8_t Token);
/** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
static inline void Pipe_SetInfiniteINRequests(void);
/** Configures the currently selected pipe to only allow the specified number of IN requests to be
* accepted by the pipe before it is automatically frozen.
*
* \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing.
*/
static inline void Pipe_SetFiniteINRequests(uint8_t TotalINRequests);
/** Determines if the currently selected pipe is configured.
*
* \return Boolean true if the selected pipe is configured, false otherwise.
*/
static inline bool Pipe_IsConfigured(void);
/** Retrieves the endpoint number of the endpoint within the attached device that the currently selected
* pipe is bound to.
*
* \return Endpoint number the currently selected pipe is bound to.
*/
static inline uint8_t Pipe_BoundEndpointNumber(void);
/** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds.
*
* \param[in] Milliseconds Number of milliseconds between each pipe poll.
*/
static inline void Pipe_SetInterruptPeriod(uint8_t Milliseconds);
/** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should
* be serviced.
*
* \return Mask whose bits indicate which pipes have interrupted.
*/
static inline uint8_t Pipe_GetPipeInterrupts(void);
/** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type
* pipes).
*
* \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested.
*
* \return Boolean true if the specified pipe has interrupted, false otherwise.
*/
static inline bool Pipe_HasPipeInterrupted(uint8_t PipeNumber);
/** Unfreezes the selected pipe, allowing it to communicate with an attached device. */
static inline void Pipe_Unfreeze(void);
/** Freezes the selected pipe, preventing it from communicating with an attached device. */
static inline void Pipe_Freeze(void);
/** Determines if the currently selected pipe is frozen, and not able to accept data.
*
* \return Boolean true if the currently selected pipe is frozen, false otherwise.
*/
static inline bool Pipe_IsFrozen(void);
/** Clears the master pipe error flag. */
static inline void Pipe_ClearError(void);
/** Determines if the master pipe error flag is set for the currently selected pipe, indicating that
* some sort of hardware error has occurred on the pipe.
*
* \see \ref Pipe_GetErrorFlags() macro for information on retrieving the exact error flag.
*
* \return Boolean true if an error has occurred on the selected pipe, false otherwise.
*/
static inline bool Pipe_IsError(void);
/** Clears all the currently selected pipe's hardware error flags, but does not clear the master error
* flag for the pipe.
*/
static inline void Pipe_ClearErrorFlags(void);
/** Gets a mask of the hardware error flags which have occurred on the currently selected pipe. This
* value can then be masked against the PIPE_ERRORFLAG_* masks to determine what error has occurred.
*
* \return Mask comprising of PIPE_ERRORFLAG_* bits indicating what error has occurred on the selected pipe.
*/
static inline uint8_t Pipe_GetErrorFlags(void);
/** Determines if the currently selected pipe may be read from (if data is waiting in the pipe
* bank and the pipe is an IN direction, or if the bank is not yet full if the pipe is an OUT
* direction). This function will return false if an error has occurred in the pipe, or if the pipe
* is an IN direction and no packet (or an empty packet) has been received, or if the pipe is an OUT
* direction and the pipe bank is full.
*
* \note This function is not valid on CONTROL type pipes.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the currently selected pipe may be read from or written to, depending on its direction.
*/
static inline bool Pipe_IsReadWriteAllowed(void);
/** Determines if an IN request has been received on the currently selected pipe.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the current pipe has received an IN packet, false otherwise.
*/
static inline bool Pipe_IsINReceived(void);
/** Determines if the currently selected pipe is ready to send an OUT request.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the current pipe is ready for an OUT packet, false otherwise.
*/
static inline bool Pipe_IsOUTReady(void);
/** Determines if no SETUP request is currently being sent to the attached device on the selected
* CONTROL type pipe.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the current pipe is ready for a SETUP packet, false otherwise.
*/
static inline bool Pipe_IsSETUPSent(void);
/** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet.
*
* \ingroup Group_PipePacketManagement
*/
static inline void Pipe_ClearSETUP(void);
/** Acknowledges the reception of a setup IN request from the attached device on the currently selected
* pipe, freeing the bank ready for the next packet.
*
* \ingroup Group_PipePacketManagement
*/
static inline void Pipe_ClearIN(void);
/** Sends the currently selected pipe's contents to the device as an OUT packet on the selected pipe, freeing
* the bank ready for the next packet.
*
* \ingroup Group_PipePacketManagement
*/
static inline void Pipe_ClearOUT(void);
/** Determines if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on
* the currently selected pipe. This occurs when the host sends a packet to the device, but the device
* is not currently ready to handle the packet (i.e. its endpoint banks are full). Once a NAK has been
* received, it must be cleared using \ref Pipe_ClearNAKReceived() before the previous (or any other) packet
* can be re-sent.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if an NAK has been received on the current pipe, false otherwise.
*/
static inline bool Pipe_IsNAKReceived(void);
/** Clears the NAK condition on the currently selected pipe.
*
* \ingroup Group_PipePacketManagement
*
* \see \ref Pipe_IsNAKReceived() for more details.
*/
static inline void Pipe_ClearNAKReceived(void);
/** Determines if the currently selected pipe has had the STALL condition set by the attached device.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the current pipe has been stalled by the attached device, false otherwise.
*/
static inline bool Pipe_IsStalled(void);
/** Clears the STALL condition detection flag on the currently selected pipe, but does not clear the
* STALL condition itself (this must be done via a ClearFeature control request to the device).
*
* \ingroup Group_PipePacketManagement
*/
static inline void Pipe_ClearStall(void);
#else
#define Pipe_BytesInPipe() UPBCX
#define Pipe_GetCurrentPipe() (UPNUM & PIPE_PIPENUM_MASK)
#define Pipe_SelectPipe(pipenum) MACROS{ UPNUM = (pipenum); }MACROE
#define Pipe_ResetPipe(pipenum) MACROS{ UPRST = (1 << (pipenum)); UPRST = 0; }MACROE
#define Pipe_EnablePipe() MACROS{ UPCONX |= (1 << PEN); }MACROE
#define Pipe_DisablePipe() MACROS{ UPCONX &= ~(1 << PEN); }MACROE
#define Pipe_IsEnabled() ((UPCONX & (1 << PEN)) ? true : false)
#define Pipe_GetPipeToken() (UPCFG0X & PIPE_TOKEN_MASK)
#define Pipe_SetPipeToken(token) MACROS{ UPCFG0X = ((UPCFG0X & ~PIPE_TOKEN_MASK) | (token)); }MACROE
#define Pipe_SetInfiniteINRequests() MACROS{ UPCONX |= (1 << INMODE); }MACROE
#define Pipe_SetFiniteINRequests(n) MACROS{ UPCONX &= ~(1 << INMODE); UPINRQX = (n); }MACROE
#define Pipe_IsConfigured() ((UPSTAX & (1 << CFGOK)) ? true : false)
#define Pipe_BoundEndpointNumber() ((UPCFG0X >> PEPNUM0) & PIPE_EPNUM_MASK)
#define Pipe_SetInterruptPeriod(ms) MACROS{ UPCFG2X = (ms); }MACROE
#define Pipe_GetPipeInterrupts() UPINT
#define Pipe_HasPipeInterrupted(n) ((UPINT & (1 << (n))) ? true : false)
#define Pipe_Unfreeze() MACROS{ UPCONX &= ~(1 << PFREEZE); }MACROE
#define Pipe_Freeze() MACROS{ UPCONX |= (1 << PFREEZE); }MACROE
#define Pipe_IsFrozen() ((UPCONX & (1 << PFREEZE)) ? true : false)
#define Pipe_ClearError() MACROS{ UPINTX &= ~(1 << PERRI); }MACROE
#define Pipe_IsError() ((UPINTX & (1 << PERRI)) ? true : false)
#define Pipe_ClearErrorFlags() MACROS{ UPERRX = 0; }MACROE
#define Pipe_GetErrorFlags() ((UPERRX & (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT | \
PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID | \
PIPE_ERRORFLAG_DATATGL)) | \
(UPSTAX & PIPE_ERRORFLAG_OVERFLOW | PIPE_ERRORFLAG_UNDERFLOW))
#define Pipe_IsReadWriteAllowed() ((UPINTX & (1 << RWAL)) ? true : false)
#define Pipe_IsINReceived() ((UPINTX & (1 << RXINI)) ? true : false)
#define Pipe_IsOUTReady() ((UPINTX & (1 << TXOUTI)) ? true : false)
#define Pipe_IsSETUPSent() ((UPINTX & (1 << TXSTPI)) ? true : false)
#define Pipe_ClearIN() MACROS{ UPINTX &= ~((1 << RXINI) | (1 << FIFOCON)); }MACROE
#define Pipe_ClearOUT() MACROS{ UPINTX &= ~((1 << TXOUTI) | (1 << FIFOCON)); }MACROE
#define Pipe_ClearSETUP() MACROS{ UPINTX &= ~((1 << TXSTPI) | (1 << FIFOCON)); }MACROE
#define Pipe_IsNAKReceived() ((UPINTX & (1 << NAKEDI)) ? true : false)
#define Pipe_ClearNAKReceived() MACROS{ UPINTX &= ~(1 << NAKEDI); }MACROE
#define Pipe_IsStalled() ((UPINTX & (1 << RXSTALLI)) ? true : false)
#define Pipe_ClearStall() MACROS{ UPINTX &= ~(1 << RXSTALLI); }MACROE
#endif
/* Enums: */
/** Enum for the possible error return codes of the Pipe_WaitUntilReady function.
*
@ -545,6 +240,386 @@
};
/* Inline Functions: */
/** Indicates the number of bytes currently stored in the current pipes's selected bank.
*
* \note The return width of this function may differ, depending on the maximum pipe bank size
* of the selected AVR model.
*
* \ingroup Group_PipeRW
*
* \return Total number of bytes in the currently selected Pipe's FIFO buffer.
*/
static inline uint16_t Pipe_BytesInPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint16_t Pipe_BytesInPipe(void)
{
return UPBCX;
}
/** Returns the pipe address of the currently selected pipe. This is typically used to save the
* currently selected pipe number so that it can be restored after another pipe has been manipulated.
*
* \return Index of the currently selected pipe.
*/
static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetCurrentPipe(void)
{
return (UPNUM & PIPE_PIPENUM_MASK);
}
/** Selects the given pipe number. Any pipe operations which do not require the pipe number to be
* indicated will operate on the currently selected pipe.
*
* \param[in] PipeNumber Index of the pipe to select.
*/
static inline void Pipe_SelectPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
static inline void Pipe_SelectPipe(const uint8_t PipeNumber)
{
UPNUM = PipeNumber;
}
/** Resets the desired pipe, including the pipe banks and flags.
*
* \param[in] PipeNumber Index of the pipe to reset.
*/
static inline void Pipe_ResetPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
static inline void Pipe_ResetPipe(const uint8_t PipeNumber)
{
UPRST = (1 << PipeNumber);
UPRST = 0;
}
/** Enables the currently selected pipe so that data can be sent and received through it to and from
* an attached device.
*
* \pre The currently selected pipe must first be configured properly via \ref Pipe_ConfigurePipe().
*/
static inline void Pipe_EnablePipe(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_EnablePipe(void)
{
UPCONX |= (1 << PEN);
}
/** Disables the currently selected pipe so that data cannot be sent and received through it to and
* from an attached device.
*/
static inline void Pipe_DisablePipe(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_DisablePipe(void)
{
UPCONX &= ~(1 << PEN);
}
/** Determines if the currently selected pipe is enabled, but not necessarily configured.
*
* \return Boolean True if the currently selected pipe is enabled, false otherwise.
*/
static inline bool Pipe_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsEnabled(void)
{
return ((UPCONX & (1 << PEN)) ? true : false);
}
/** Gets the current pipe token, indicating the pipe's data direction and type.
*
* \return The current pipe token, as a PIPE_TOKEN_* mask.
*/
static inline uint8_t Pipe_GetPipeToken(void) ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetPipeToken(void)
{
return (UPCFG0X & (0x03 << PTOKEN0));
}
/** Sets the token for the currently selected pipe to one of the tokens specified by the PIPE_TOKEN_*
* masks. This can be used on CONTROL type pipes, to allow for bidirectional transfer of data during
* control requests, or on regular pipes to allow for half-duplex bidirectional data transfer to devices
* which have two endpoints of opposite direction sharing the same endpoint address within the device.
*
* \param[in] Token New pipe token to set the selected pipe to, as a PIPE_TOKEN_* mask.
*/
static inline void Pipe_SetPipeToken(const uint8_t Token) ATTR_ALWAYS_INLINE;
static inline void Pipe_SetPipeToken(const uint8_t Token)
{
UPCFG0X = ((UPCFG0X & ~(0x03 << PTOKEN0)) | Token);
}
/** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
static inline void Pipe_SetInfiniteINRequests(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_SetInfiniteINRequests(void)
{
UPCONX |= (1 << INMODE);
}
/** Configures the currently selected pipe to only allow the specified number of IN requests to be
* accepted by the pipe before it is automatically frozen.
*
* \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing.
*/
static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests) ATTR_ALWAYS_INLINE;
static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests)
{
UPCONX &= ~(1 << INMODE);
UPINRQX = TotalINRequests;
}
/** Determines if the currently selected pipe is configured.
*
* \return Boolean true if the selected pipe is configured, false otherwise.
*/
static inline bool Pipe_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsConfigured(void)
{
return ((UPSTAX & (1 << CFGOK)) ? true : false);
}
/** Retrieves the endpoint number of the endpoint within the attached device that the currently selected
* pipe is bound to.
*
* \return Endpoint number the currently selected pipe is bound to.
*/
static inline uint8_t Pipe_BoundEndpointNumber(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_BoundEndpointNumber(void)
{
return ((UPCFG0X >> PEPNUM0) & PIPE_EPNUM_MASK);
}
/** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds.
*
* \param[in] Milliseconds Number of milliseconds between each pipe poll.
*/
static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds) ATTR_ALWAYS_INLINE;
static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds)
{
UPCFG2X = Milliseconds;
}
/** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should
* be serviced.
*
* \return Mask whose bits indicate which pipes have interrupted.
*/
static inline uint8_t Pipe_GetPipeInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetPipeInterrupts(void)
{
return UPINT;
}
/** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type
* pipes).
*
* \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested.
*
* \return Boolean true if the specified pipe has interrupted, false otherwise.
*/
static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber)
{
return ((UPINT & (1 << PipeNumber)) ? true : false);
}
/** Unfreezes the selected pipe, allowing it to communicate with an attached device. */
static inline void Pipe_Unfreeze(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Unfreeze(void)
{
UPCONX &= ~(1 << PFREEZE);
}
/** Freezes the selected pipe, preventing it from communicating with an attached device. */
static inline void Pipe_Freeze(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_Freeze(void)
{
UPCONX |= (1 << PFREEZE);
}
/** Determines if the currently selected pipe is frozen, and not able to accept data.
*
* \return Boolean true if the currently selected pipe is frozen, false otherwise.
*/
static inline bool Pipe_IsFrozen(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsFrozen(void)
{
return ((UPCONX & (1 << PFREEZE)) ? true : false);
}
/** Clears the master pipe error flag. */
static inline void Pipe_ClearError(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearError(void)
{
UPINTX &= ~(1 << PERRI);
}
/** Determines if the master pipe error flag is set for the currently selected pipe, indicating that
* some sort of hardware error has occurred on the pipe.
*
* \see \ref Pipe_GetErrorFlags() macro for information on retrieving the exact error flag.
*
* \return Boolean true if an error has occurred on the selected pipe, false otherwise.
*/
static inline bool Pipe_IsError(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsError(void)
{
return ((UPINTX & (1 << PERRI)) ? true : false);
}
/** Clears all the currently selected pipe's hardware error flags, but does not clear the master error
* flag for the pipe.
*/
static inline void Pipe_ClearErrorFlags(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearErrorFlags(void)
{
UPERRX = 0;
}
/** Gets a mask of the hardware error flags which have occurred on the currently selected pipe. This
* value can then be masked against the PIPE_ERRORFLAG_* masks to determine what error has occurred.
*
* \return Mask comprising of PIPE_ERRORFLAG_* bits indicating what error has occurred on the selected pipe.
*/
static inline uint8_t Pipe_GetErrorFlags(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t Pipe_GetErrorFlags(void)
{
return ((UPERRX & (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT |
PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID |
PIPE_ERRORFLAG_DATATGL)) |
(UPSTAX & (PIPE_ERRORFLAG_OVERFLOW | PIPE_ERRORFLAG_UNDERFLOW)));
}
/** Determines if the currently selected pipe may be read from (if data is waiting in the pipe
* bank and the pipe is an IN direction, or if the bank is not yet full if the pipe is an OUT
* direction). This function will return false if an error has occurred in the pipe, or if the pipe
* is an IN direction and no packet (or an empty packet) has been received, or if the pipe is an OUT
* direction and the pipe bank is full.
*
* \note This function is not valid on CONTROL type pipes.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the currently selected pipe may be read from or written to, depending on its direction.
*/
static inline bool Pipe_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsReadWriteAllowed(void)
{
return ((UPINTX & (1 << RWAL)) ? true : false);
}
/** Determines if an IN request has been received on the currently selected pipe.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the current pipe has received an IN packet, false otherwise.
*/
static inline bool Pipe_IsINReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsINReceived(void)
{
return ((UPINTX & (1 << RXINI)) ? true : false);
}
/** Determines if the currently selected pipe is ready to send an OUT request.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the current pipe is ready for an OUT packet, false otherwise.
*/
static inline bool Pipe_IsOUTReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsOUTReady(void)
{
return ((UPINTX & (1 << TXOUTI)) ? true : false);
}
/** Determines if no SETUP request is currently being sent to the attached device on the selected
* CONTROL type pipe.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the current pipe is ready for a SETUP packet, false otherwise.
*/
static inline bool Pipe_IsSETUPSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsSETUPSent(void)
{
return ((UPINTX & (1 << TXSTPI)) ? true : false);
}
/** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet.
*
* \ingroup Group_PipePacketManagement
*/
static inline void Pipe_ClearSETUP(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearSETUP(void)
{
UPINTX &= ~((1 << TXSTPI) | (1 << FIFOCON));
}
/** Acknowledges the reception of a setup IN request from the attached device on the currently selected
* pipe, freeing the bank ready for the next packet.
*
* \ingroup Group_PipePacketManagement
*/
static inline void Pipe_ClearIN(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearIN(void)
{
UPINTX &= ~((1 << RXINI) | (1 << FIFOCON));
}
/** Sends the currently selected pipe's contents to the device as an OUT packet on the selected pipe, freeing
* the bank ready for the next packet.
*
* \ingroup Group_PipePacketManagement
*/
static inline void Pipe_ClearOUT(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearOUT(void)
{
UPINTX &= ~((1 << TXOUTI) | (1 << FIFOCON));
}
/** Determines if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on
* the currently selected pipe. This occurs when the host sends a packet to the device, but the device
* is not currently ready to handle the packet (i.e. its endpoint banks are full). Once a NAK has been
* received, it must be cleared using \ref Pipe_ClearNAKReceived() before the previous (or any other) packet
* can be re-sent.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if an NAK has been received on the current pipe, false otherwise.
*/
static inline bool Pipe_IsNAKReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsNAKReceived(void)
{
return ((UPINTX & (1 << NAKEDI)) ? true : false);
}
/** Clears the NAK condition on the currently selected pipe.
*
* \ingroup Group_PipePacketManagement
*
* \see \ref Pipe_IsNAKReceived() for more details.
*/
static inline void Pipe_ClearNAKReceived(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearNAKReceived(void)
{
UPINTX &= ~(1 << NAKEDI);
}
/** Determines if the currently selected pipe has had the STALL condition set by the attached device.
*
* \ingroup Group_PipePacketManagement
*
* \return Boolean true if the current pipe has been stalled by the attached device, false otherwise.
*/
static inline bool Pipe_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Pipe_IsStalled(void)
{
return ((UPINTX & (1 << RXSTALLI)) ? true : false);
}
/** Clears the STALL condition detection flag on the currently selected pipe, but does not clear the
* STALL condition itself (this must be done via a ClearFeature control request to the device).
*
* \ingroup Group_PipePacketManagement
*/
static inline void Pipe_ClearStall(void) ATTR_ALWAYS_INLINE;
static inline void Pipe_ClearStall(void)
{
UPINTX &= ~(1 << RXSTALLI);
}
/** Reads one byte from the currently selected pipe's bank, for OUT direction pipes.
*
* \ingroup Group_PipePrimitiveRW
@ -1046,14 +1121,7 @@
__CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1);
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define PIPE_TOKEN_MASK (0x03 << PTOKEN0)
#if !defined(ENDPOINT_CONTROLEP)
#define ENDPOINT_CONTROLEP 0
#endif
#if !defined(__DOXYGEN__)
/* Function Prototypes: */
void Pipe_ClearPipes(void);

@ -196,20 +196,40 @@
*/
#define EP_TYPE_INTERRUPT 0x03
#if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__)
/** Constant for the maximum software timeout period of the USB data stream transfer functions
* (both control and standard) when in either device or host mode. If the next packet of a stream
* is not received or acknowledged within this time period, the stream function will fail.
*
* This value may be overridden in the user project makefile as the value of the
* \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
*/
#define USB_STREAM_TIMEOUT_MS 100
#endif
/* Inline Functions: */
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
/** Returns boolean true if the VBUS line is currently high (i.e. the USB host is supplying power),
* otherwise returns false.
*
* \note This token is not available on some AVR models which do not support hardware VBUS monitoring.
* \note This function is not available on some AVR models which do not support hardware VBUS monitoring.
*/
#define USB_VBUS_GetStatus() ((USBSTA & (1 << VBUS)) ? true : false)
static inline bool USB_VBUS_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_VBUS_GetStatus(void)
{
return ((USBSTA & (1 << VBUS)) ? true : false);
}
#endif
/** Detaches the device from the USB bus. This has the effect of removing the device from any
* attached host, ceasing USB communications. If no host is present, this prevents any host from
* enumerating the device once attached until \ref USB_Attach() is called.
*/
#define USB_Detach() MACROS{ UDCON |= (1 << DETACH); }MACROE
static inline void USB_Detach(void) ATTR_ALWAYS_INLINE;
static inline void USB_Detach(void)
{
UDCON |= (1 << DETACH);
}
/** Attaches the device to the USB bus. This announces the device's presence to any attached
* USB host, starting the enumeration process. If no host is present, attaching the device
@ -219,18 +239,11 @@
* attachment of a device to the host. This is despite the bit being located in the device-mode
* register and despite the datasheet making no mention of its requirement in host mode.
*/
#define USB_Attach() MACROS{ UDCON &= ~(1 << DETACH); }MACROE
#if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__)
/** Constant for the maximum software timeout period of the USB data stream transfer functions
* (both control and standard) when in either device or host mode. If the next packet of a stream
* is not received or acknowledged within this time period, the stream function will fail.
*
* This value may be overridden in the user project makefile as the value of the
* \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
*/
#define USB_STREAM_TIMEOUT_MS 100
#endif
static inline void USB_Attach(void) ATTR_ALWAYS_INLINE;
static inline void USB_Attach(void)
{
UDCON &= ~(1 << DETACH);
}
/* Function Prototypes: */
/** Main function to initialize and start the USB interface. Once active, the USB interface will
@ -342,31 +355,93 @@
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define USB_PLL_On() MACROS{ PLLCSR = USB_PLL_PSC; PLLCSR |= (1 << PLLE); }MACROE
#define USB_PLL_Off() MACROS{ PLLCSR = 0; }MACROE
#define USB_PLL_IsReady() ((PLLCSR & (1 << PLOCK)) ? true : false)
/* Inline Functions: */
static inline void USB_PLL_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_PLL_On(void)
{
PLLCSR = USB_PLL_PSC;
PLLCSR |= (1 << PLLE);
}
static inline void USB_PLL_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_PLL_Off(void)
{
PLLCSR = 0;
}
static inline bool USB_PLL_IsReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool USB_PLL_IsReady(void)
{
return ((PLLCSR & (1 << PLOCK)) ? true : false);
}
static inline void USB_REG_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_REG_On(void)
{
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
UHWCON |= (1 << UVREGE);
#else
REGCR &= ~(1 << REGDIS);
#endif
}
static inline void USB_REG_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_REG_Off(void)
{
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
#define USB_REG_On() MACROS{ UHWCON |= (1 << UVREGE); }MACROE
#define USB_REG_Off() MACROS{ UHWCON &= ~(1 << UVREGE); }MACROE
UHWCON &= ~(1 << UVREGE);
#else
#define USB_REG_On() MACROS{ REGCR &= ~(1 << REGDIS); }MACROE
#define USB_REG_Off() MACROS{ REGCR |= (1 << REGDIS); }MACROE
REGCR |= (1 << REGDIS);
#endif
}
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
static inline void USB_OTGPAD_On(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTGPAD_On(void)
{
USBCON |= (1 << OTGPADE);
}
static inline void USB_OTGPAD_Off(void) ATTR_ALWAYS_INLINE;
static inline void USB_OTGPAD_Off(void)
{
USBCON &= ~(1 << OTGPADE);
}
#endif
static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE;
static inline void USB_CLK_Freeze(void)
{
USBCON |= (1 << FRZCLK);
}
static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE;
static inline void USB_CLK_Unfreeze(void)
{
USBCON &= ~(1 << FRZCLK);
}
#define USB_OTGPAD_On() MACROS{ USBCON |= (1 << OTGPADE); }MACROE
#define USB_OTGPAD_Off() MACROS{ USBCON &= ~(1 << OTGPADE); }MACROE
static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Enable(void)
{
USBCON |= (1 << USBE);
}
#define USB_CLK_Freeze() MACROS{ USBCON |= (1 << FRZCLK); }MACROE
#define USB_CLK_Unfreeze() MACROS{ USBCON &= ~(1 << FRZCLK); }MACROE
static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Disable(void)
{
USBCON &= ~(1 << USBE);
}
#define USB_Controller_Enable() MACROS{ USBCON |= (1 << USBE); }MACROE
#define USB_Controller_Disable() MACROS{ USBCON &= ~(1 << USBE); }MACROE
#define USB_Controller_Reset() MACROS{ const uint8_t Temp = USBCON; USBCON = (Temp & ~(1 << USBE)); \
USBCON = (Temp | (1 << USBE)); }MACROE
static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;
static inline void USB_Controller_Reset(void)
{
const uint8_t Temp = USBCON;
USBCON = (Temp & ~(1 << USBE));
USBCON = (Temp | (1 << USBE));
}
/* Inline Functions: */
#if defined(USB_CAN_BE_BOTH)
static inline uint8_t USB_GetUSBModeFromUID(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline uint8_t USB_GetUSBModeFromUID(void)

@ -47,11 +47,6 @@
#include <util/atomic.h>
#include <stdbool.h>
#include "../../../Common/Common.h"
#include "../HighLevel/USBMode.h"
#include "../HighLevel/Events.h"
#include "USBController.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
@ -90,6 +85,12 @@
#define USB_INT_RSTI UHIEN , (1 << RSTE) , UHINT , (1 << RSTI)
#define USB_INT_SRPI OTGIEN, (1 << SRPE) , OTGINT, (1 << SRPI)
#define USB_INT_RXSTPI UEIENX, (1 << RXSTPE) , UEINTX, (1 << RXSTPI)
/* Includes: */
#include "../../../Common/Common.h"
#include "../HighLevel/USBMode.h"
#include "../HighLevel/Events.h"
#include "USBController.h"
/* Function Prototypes: */
void USB_INT_ClearAllInterrupts(void);

@ -36,6 +36,7 @@
* - Removed the automated checking of event names in the demo, project and bootloader makefiles due to inconsistancies between the
* behaviour of the command line tools used to perform the check on each platform
* - Internal USB driver source files renamed and moved to ease future possible architecture ports
* - All internal pseudo-function macros have been converted to true inline functions for type-safety and readability
*
* <b>Fixed:</b>
* - Fixed AVRISP project sending a LOAD EXTENDED ADDRESS command to 128KB AVRs after programming or reading from

@ -12,6 +12,11 @@
*
* \section Sec_Migration100513 Migrating from 100513 to XXXXXX
*
* <b>Non-USB Library Components</b>
* - The Dataflash board driver stub file has changed, as dataflash functions previously located in the internal
* Dataflash driver of the library have now been moved to the individual board files. Existing drivers can
* copy-paste the new functions from the board Dataflash stub driver.
*
* <b>USB Core</b>
* - A new USB driver source file, Drivers/USB/LowLevel/Device.c now exists. This source file should be added to all project
* makefiles using the USB driver of LUFA, or the makefile should be updated to use the new module source variables.

Loading…
Cancel
Save