diff --git a/LUFA.pnproj b/LUFA.pnproj index 800f6106e4..25e69da4ed 100644 --- a/LUFA.pnproj +++ b/LUFA.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/LUFA/CodeTemplates/DriverStubs/Dataflash.h b/LUFA/CodeTemplates/DriverStubs/Dataflash.h index 711d1f8dba..9fcc25f9bb 100644 --- a/LUFA/CodeTemplates/DriverStubs/Dataflash.h +++ b/LUFA/CodeTemplates/DriverStubs/Dataflash.h @@ -97,7 +97,7 @@ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) { - return SPI_TransferByte(Byte); + // TODO } /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash. @@ -107,7 +107,7 @@ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; static inline void Dataflash_SendByte(const uint8_t Byte) { - SPI_SendByte(Byte); + // TODO } /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash. @@ -117,7 +117,7 @@ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; static inline uint8_t Dataflash_ReceiveByte(void) { - return SPI_ReceiveByte(); + // TODO } /** Determines the currently selected dataflash chip. diff --git a/LUFA/DoxygenPages/ChangeLog.txt b/LUFA/DoxygenPages/ChangeLog.txt index 2bdebbe878..dde6a6b45e 100644 --- a/LUFA/DoxygenPages/ChangeLog.txt +++ b/LUFA/DoxygenPages/ChangeLog.txt @@ -20,7 +20,8 @@ * - Added support for the Micropendous family of boards (Arduino-like revisions 1 and 2, DIP, 32U2, A, 1, 2, 3 and 4) * - Added INVERTED_VBUS_ENABLE_LINE and NO_AUTO_VBUS_MANAGEMENT compile time options (thanks to Opendous Inc.) * - Added support for the Atmel XMEGA B1 Xplained board - * - Added Serial USART peripheral driver for the XMEGA platform + * - Added Serial USART peripheral driver for the XMEGA architecture + * - Added Master Mode SPI USART peripheral driver for the XMEGA and AVR8 architectures * - Library Applications: * - Added User Application APIs to the CDC and DFU class bootloaders * - Added INVERTED_ISP_MISO compile time option to the AVRISP-MKII clone project (thanks to Chuck Rohs) diff --git a/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h b/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h index 007ef94ffc..595492fe20 100644 --- a/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h +++ b/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h @@ -51,6 +51,7 @@ /* Includes: */ #include "../../../../Common/Common.h" #include "../../../Misc/AT45DB321C.h" + #include "../../../Peripheral/SPI.h" /* Preprocessor Checks: */ #if !defined(__INCLUDE_FROM_DATAFLASH_H) diff --git a/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h b/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h index c9d6477fa9..67742977ce 100644 --- a/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h +++ b/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h @@ -51,6 +51,7 @@ /* Includes: */ #include "../../../../Common/Common.h" #include "../../../Misc/AT45DB321C.h" + #include "../../../Peripheral/SPI.h" /* Preprocessor Checks: */ #if !defined(__INCLUDE_FROM_DATAFLASH_H) diff --git a/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h b/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h index ea4c0a0218..ce20ff1e78 100644 --- a/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h +++ b/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h @@ -51,6 +51,7 @@ /* Includes: */ #include "../../../../Common/Common.h" #include "../../../Misc/AT45DB642D.h" + #include "../../../Peripheral/SPI.h" /* Preprocessor Checks: */ #if !defined(__INCLUDE_FROM_DATAFLASH_H) diff --git a/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h b/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h index 1e34a39531..5b71d7d887 100644 --- a/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h +++ b/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h @@ -51,6 +51,7 @@ /* Includes: */ #include "../../../../Common/Common.h" #include "../../../Misc/AT45DB642D.h" + #include "../../../Peripheral/SPI.h" /* Preprocessor Checks: */ #if !defined(__INCLUDE_FROM_DATAFLASH_H) diff --git a/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h b/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h index 62532ced1c..c9bdbdc3a1 100644 --- a/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h +++ b/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h @@ -60,6 +60,7 @@ /* Includes: */ #include "../../../../Common/Common.h" #include "../../../Misc/AT45DB642D.h" + #include "../../../Peripheral/SPI.h" /* Preprocessor Checks: */ #if !defined(__INCLUDE_FROM_DATAFLASH_H) diff --git a/LUFA/Drivers/Board/Dataflash.h b/LUFA/Drivers/Board/Dataflash.h index 2e1336bf61..a5ae29dc8e 100644 --- a/LUFA/Drivers/Board/Dataflash.h +++ b/LUFA/Drivers/Board/Dataflash.h @@ -123,7 +123,6 @@ /* Includes: */ #include "../../Common/Common.h" - #include "../Peripheral/SPI.h" /* Enable C linkage for C++ Compilers: */ #if defined(__cplusplus) @@ -148,7 +147,9 @@ /* Inline Functions: */ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC. * - * \note The microcontroller's SPI driver must be initialized before any of the dataflash commands are used. + * \note The microcontroller's physical interface driver connected to the Dataflash IC must be initialized before + * any of the dataflash commands are used. This is usually a SPI hardware port, but on some devices/boards may + * be a USART operating in SPI Master mode. */ static inline void Dataflash_Init(void); diff --git a/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h b/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h index c263853ee0..abc8d85d11 100644 --- a/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h +++ b/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h @@ -51,6 +51,7 @@ /* Includes: */ #include "../../../../Common/Common.h" #include "../../../Misc/AT45DB642D.h" + #include "../../../Peripheral/SerialSPI.h" /* Preprocessor Checks: */ #if !defined(__INCLUDE_FROM_DATAFLASH_H) @@ -100,9 +101,7 @@ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) { - // TODO: USART in SPI mode on PORT D - #warning The Dataflash driver for the selected board is currently incomplete and non-functional. - return 0; + return SerialSPI_TransferByte(&USARTD0, Byte); } /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash. @@ -112,7 +111,7 @@ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; static inline void Dataflash_SendByte(const uint8_t Byte) { - return; // TODO + SerialSPI_SendByte(&USARTD0, Byte); } /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash. @@ -122,7 +121,7 @@ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; static inline uint8_t Dataflash_ReceiveByte(void) { - return 0; // TODO + return SerialSPI_ReceiveByte(&USARTD0); } /** Determines the currently selected dataflash chip. @@ -170,10 +169,7 @@ if (PageAddress >= (DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS)) return; - if (PageAddress & 0x01) - Dataflash_SelectChip(DATAFLASH_CHIP2); - else - Dataflash_SelectChip(DATAFLASH_CHIP1); + Dataflash_SelectChip(DATAFLASH_CHIP1); } /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive @@ -207,8 +203,6 @@ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, const uint16_t BufferByte) { - PageAddress >>= 1; - Dataflash_SendByte(PageAddress >> 5); Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8)); Dataflash_SendByte(BufferByte); diff --git a/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h b/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h index 74a215b6c5..e12f969e62 100644 --- a/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h +++ b/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h @@ -51,6 +51,7 @@ /* Includes: */ #include "../../../../Common/Common.h" #include "../../../Misc/AT45DB642D.h" + #include "../../../Peripheral/SerialSPI.h" /* Preprocessor Checks: */ #if !defined(__INCLUDE_FROM_DATAFLASH_H) @@ -100,9 +101,7 @@ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) { - // TODO: USART in SPI mode on PORT C - #warning The Dataflash driver for the selected board is currently incomplete and non-functional. - return 0; + return SerialSPI_TransferByte(&USARTE0, Byte); } /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash. @@ -112,7 +111,7 @@ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE; static inline void Dataflash_SendByte(const uint8_t Byte) { - return; // TODO + SerialSPI_SendByte(&USARTE0, Byte); } /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash. @@ -122,7 +121,7 @@ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; static inline uint8_t Dataflash_ReceiveByte(void) { - return 0; // TODO + return SerialSPI_ReceiveByte(&USARTE0); } /** Determines the currently selected dataflash chip. @@ -170,10 +169,7 @@ if (PageAddress >= (DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS)) return; - if (PageAddress & 0x01) - Dataflash_SelectChip(DATAFLASH_CHIP2); - else - Dataflash_SelectChip(DATAFLASH_CHIP1); + Dataflash_SelectChip(DATAFLASH_CHIP1); } /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive @@ -207,8 +203,6 @@ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, const uint16_t BufferByte) { - PageAddress >>= 1; - Dataflash_SendByte(PageAddress >> 5); Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8)); Dataflash_SendByte(BufferByte); diff --git a/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h b/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h new file mode 100644 index 0000000000..fe108e500d --- /dev/null +++ b/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h @@ -0,0 +1,205 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2012. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Serial USART Master SPI Mode Peripheral Driver (XMEGA) + * + * On-chip Master SPI mode USART driver for the XMEGA AVR microcontrollers. + * + * \note This file should not be included directly. It is automatically included as needed by the SPI Master + * Mode USART driver dispatch header located in LUFA/Drivers/Peripheral/Serial.h. + */ + +/** \ingroup Group_SerialSPI + * \defgroup Group_SerialSPI_AVR8 Serial USART Peripheral Driver (AVR8) + * + * \section Sec_ModDescription Module Description + * On-chip serial USART driver for the 8-bit AVR8 microcontrollers. + * + * \note This file should not be included directly. It is automatically included as needed by the SPI Master + * driver dispatch header located in LUFA/Drivers/Peripheral/SerialSPI.h. + * + * \section Sec_ExampleUsage Example Usage + * The following snippet is an example of how this module may be used within a typical + * application. + * + * \code + * // Initialize the Master SPI mode USART driver before first use, with 1Mbit baud + * SerialSPI_Init((USART_SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_ORDER_MSB_FIRST), 1000000); + * + * // Send several bytes, ignoring the returned data + * SerialSPI_SendByte(0x01); + * SerialSPI_SendByte(0x02); + * SerialSPI_SendByte(0x03); + * + * // Receive several bytes, sending a dummy 0x00 byte each time + * uint8_t Byte1 = SerialSPI_ReceiveByte(); + * uint8_t Byte2 = SerialSPI_ReceiveByte(); + * uint8_t Byte3 = SerialSPI_ReceiveByte(); + * + * // Send a byte, and store the received byte from the same transaction + * uint8_t ResponseByte = SerialSPI_TransferByte(0xDC); + * \endcode + * + * @{ + */ + +#ifndef __SERIAL_SPI_AVR8_H__ +#define __SERIAL_SPI_AVR8_H__ + + /* Includes: */ + #include "../../../Common/Common.h" + + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_SERIAL_SPI_H) + #error Do not include this file directly. Include LUFA/Drivers/Peripheral/Serial.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + #define SERIAL_SPI_UBBRVAL(Baud) ((Baud < (F_CPU / 2)) ? ((F_CPU / (2 * Baud)) - 1) : 0) + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name SPI SCK Polarity Configuration Masks */ + //@{ + /** SPI clock polarity mask for \c SPI_Init(). Indicates that the SCK should lead on the rising edge. */ + #define USART_SPI_SCK_LEAD_RISING (0 << UCPOL) + + /** SPI clock polarity mask for \c SPI_Init(). Indicates that the SCK should lead on the falling edge. */ + #define USART_SPI_SCK_LEAD_FALLING (1 << UCPOL) + //@} + + /** \name SPI Sample Edge Configuration Masks */ + //@{ + /** SPI data sample mode mask for \c SerialSPI_Init(). Indicates that the data should sampled on the leading edge. */ + #define USART_SPI_SAMPLE_LEADING (0 << UPCHA) + + /** SPI data sample mode mask for \c SerialSPI_Init(). Indicates that the data should be sampled on the trailing edge. */ + #define USART_SPI_SAMPLE_TRAILING (1 << UPCHA) + //@} + + /** \name SPI Data Ordering Configuration Masks */ + //@{ + /** SPI data order mask for \c Serial_SPIInit(). Indicates that data should be shifted out MSB first. */ + #define USART_SPI_ORDER_MSB_FIRST (0 << UDORD) + + /** SPI data order mask for \c Serial_SPIInit(). Indicates that data should be shifted out LSB first. */ + #define USART_SPI_ORDER_LSB_FIRST (1 << UDORD) + //@} + + /* Inline Functions: */ + /** Initialize the USART module in Master SPI mode. + * + * \param[in] SPIOptions USART SPI Options, a mask consisting of one of each of the \c USART_SPI_SCK_*, + * \c USART_SPI_SAMPLE_* and \c USART_SPI_ORDER_* masks. + * \param[in] BaudRate SPI baud rate, in bits per second. + */ + static inline void SerialSPI_Init(const uint8_t SPIOptions, + const uint32_t BaudRate) + { + UBRR1 = SERIAL_SPI_UBBRVAL(BaudRate); + + UCSR1C = ((1 << UMSEL11) | (1 << UMSEL10) | SPIOptions); + UCSR1B = ((1 << TXEN1) | (1 << RXEN1)); + + DDRD |= (1 << 3); + PORTD |= (1 << 2); + } + + /** Turns off the USART driver, disabling and returning used hardware to their default configuration. */ + static inline void SerialSPI_Disable(void) + { + UCSR1B = 0; + UCSR1A = 0; + UCSR1C = 0; + + UBRR1 = 0; + + DDRD &= ~(1 << 3); + PORTD &= ~(1 << 2); + } + + /** Sends and receives a byte through the USART SPI interface, blocking until the transfer is complete. + * + * \param[in] DataByte Byte to send through the USART SPI interface. + * + * \return Response byte from the attached SPI device. + */ + static inline uint8_t SerialSPI_TransferByte(const uint8_t DataByte) + { + UDR1 = DataByte; + while (!(UCSR1A & (1 << TXC1))); + UCSR1A = (1 << TXC1); + return UDR1; + } + + /** Sends a byte through the USART SPI interface, blocking until the transfer is complete. The response + * byte sent to from the attached SPI device is ignored. + * + * \param[in] DataByte Byte to send through the USART SPI interface. + */ + static inline void SerialSPI_SendByte(const uint8_t DataByte) + { + UDR1 = DataByte; + while (!(UCSR1A & (1 << TXC1))); + UCSR1A = (1 << TXC1); + } + + /** Sends a dummy byte through the USART SPI interface, blocking until the transfer is complete. The response + * byte from the attached SPI device is returned. + * + * \return The response byte from the attached SPI device. + */ + static inline uint8_t SerialSPI_ReceiveByte(void) + { + UDR1 = 0; + while (!(UCSR1A & (1 << TXC1))); + UCSR1A = (1 << TXC1); + return UDR1; + } + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ + diff --git a/LUFA/Drivers/Peripheral/SerialSPI.h b/LUFA/Drivers/Peripheral/SerialSPI.h new file mode 100644 index 0000000000..f5eede842b --- /dev/null +++ b/LUFA/Drivers/Peripheral/SerialSPI.h @@ -0,0 +1,76 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2012. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Hardware SPI Master Mode Serial USART driver. + * + * This file is the master dispatch header file for the device-specific SPI Master Mode USART driver, for + * microcontrollers containing a hardware USART capable of operating in a Master SPI mode. + * + * User code should include this file, which will in turn include the correct ADC driver header file for the + * currently selected architecture and microcontroller model. + */ + +/** \ingroup Group_PeripheralDrivers + * \defgroup Group_SerialSPI Master SPI Mode Serial USART Driver - LUFA/Drivers/Peripheral/SerialSPI.h + * \brief Hardware SPI Master Mode Serial USART driver. + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - None + * + * \section Sec_ModDescription Module Description + * Hardware SPI Master Mode serial USART driver. This module provides an easy to use driver for the setup and transfer + * of data over the selected architecture and microcontroller model's USART port, using a SPI framing format. + * + * \note The exact API for this driver may vary depending on the target used - see + * individual target module documentation for the API specific to your target processor. + */ + +#ifndef __SERIAL_SPI_H__ +#define __SERIAL_SPI_H__ + + /* Macros: */ + #define __INCLUDE_FROM_SERIAL_SPI_H + + /* Includes: */ + #include "../../Common/Common.h" + + /* Includes: */ + #if (ARCH == ARCH_AVR8) + #include "AVR8/SerialSPI_AVR8.h" + #elif (ARCH == ARCH_XMEGA) + #include "XMEGA/SerialSPI_XMEGA.h" + #else + #error The Serial SPI Master Mode peripheral driver is not currently available for your selected architecture. + #endif + +#endif + diff --git a/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h b/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h new file mode 100644 index 0000000000..7d1e6c1f3e --- /dev/null +++ b/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h @@ -0,0 +1,208 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2012. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * \brief Serial USART Master SPI Mode Peripheral Driver (XMEGA) + * + * On-chip Master SPI mode USART driver for the XMEGA AVR microcontrollers. + * + * \note This file should not be included directly. It is automatically included as needed by the SPI Master + * Mode USART driver dispatch header located in LUFA/Drivers/Peripheral/Serial.h. + */ + +/** \ingroup Group_SerialSPI + * \defgroup Group_SerialSPI_XMEGA Serial USART Peripheral Driver (XMEGA) + * + * \section Sec_ModDescription Module Description + * On-chip serial USART driver for the XMEGA AVR microcontrollers. + * + * \note This file should not be included directly. It is automatically included as needed by the ADC driver + * dispatch header located in LUFA/Drivers/Peripheral/SerialSPI.h. + * + * \section Sec_ExampleUsage Example Usage + * The following snippet is an example of how this module may be used within a typical + * application. + * + * \code + * // Initialize the Master SPI mode USART driver before first use, with 1Mbit baud + * SerialSPI_Init(&USARTD, (USART_SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_ORDER_MSB_FIRST), 1000000); + * + * // Send several bytes, ignoring the returned data + * SerialSPI_SendByte(&USARTD, 0x01); + * SerialSPI_SendByte(&USARTD, 0x02); + * SerialSPI_SendByte(&USARTD, 0x03); + * + * // Receive several bytes, sending a dummy 0x00 byte each time + * uint8_t Byte1 = SerialSPI_ReceiveByte(&USARTD); + * uint8_t Byte2 = SerialSPI_ReceiveByte(&USARTD); + * uint8_t Byte3 = SerialSPI_ReceiveByte(&USARTD); + * + * // Send a byte, and store the received byte from the same transaction + * uint8_t ResponseByte = SerialSPI_TransferByte(&USARTD, 0xDC); + * \endcode + * + * @{ + */ + +#ifndef __SERIAL_SPI_XMEGA_H__ +#define __SERIAL_SPI_XMEGA_H__ + + /* Includes: */ + #include "../../../Common/Common.h" + + #include + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Preprocessor Checks: */ + #if !defined(__INCLUDE_FROM_SERIAL_SPI_H) + #error Do not include this file directly. Include LUFA/Drivers/Peripheral/Serial.h instead. + #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + #define SERIAL_SPI_UBBRVAL(Baud) ((Baud < (F_CPU / 2)) ? ((F_CPU / (2 * Baud)) - 1) : 0) + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** \name SPI SCK Polarity Configuration Masks */ + //@{ + /** SPI clock polarity mask for \c SerialSPI_Init(). Indicates that the SCK should lead on the rising edge. */ + #define USART_SPI_SCK_LEAD_RISING 0 + //@} + + /** \name SPI Sample Edge Configuration Masks */ + //@{ + /** SPI data sample mode mask for \c SerialSPI_Init(). Indicates that the data should sampled on the leading edge. */ + #define USART_SPI_SAMPLE_LEADING 0 + + /** SPI data sample mode mask for \c SerialSPI_Init(). Indicates that the data should be sampled on the trailing edge. */ + #define USART_SPI_SAMPLE_TRAILING USART_UPCHA_bm + //@} + + /** \name SPI Data Ordering Configuration Masks */ + //@{ + /** SPI data order mask for \c Serial_SPIInit(). Indicates that data should be shifted out MSB first. */ + #define USART_SPI_ORDER_MSB_FIRST 0 + + /** SPI data order mask for \c Serial_SPIInit(). Indicates that data should be shifted out LSB first. */ + #define USART_SPI_ORDER_LSB_FIRST USART_UDORD_bm + //@} + + /* Inline Functions: */ + /** Initialize the USART module in Master SPI mode. + * + * \param[in,out] USART Pointer to the base of the USART peripheral within the device. + * \param[in] SPIOptions USART SPI Options, a mask consisting of one of each of the \c USART_SPI_SCK_*, + * \c USART_SPI_SAMPLE_* and \c USART_SPI_ORDER_* masks. + * \param[in] BaudRate SPI baud rate, in bits per second. + */ + static inline void SerialSPI_Init(USART_t* const USART, + const uint8_t SPIOptions, + const uint32_t BaudRate) + { + uint16_t BaudValue = SERIAL_SPI_UBBRVAL(BaudRate); + + USART->BAUDCTRLB = (BaudValue >> 8); + USART->BAUDCTRLA = (BaudValue & 0xFF); + + USART->CTRLC = (USART_CMODE_MSPI_gc | SPIOptions); + USART->CTRLB = (USART_RXEN_bm | USART_TXEN_bm); + } + + /** Turns off the USART driver, disabling and returning used hardware to their default configuration. + * + * \param[in,out] USART Pointer to the base of the USART peripheral within the device. + */ + static inline void SerialSPI_Disable(USART_t* const USART) + { + USART->CTRLA = 0; + USART->CTRLB = 0; + USART->CTRLC = 0; + } + + /** Sends and receives a byte through the USART SPI interface, blocking until the transfer is complete. + * + * \param[in,out] USART Pointer to the base of the USART peripheral within the device. + * \param[in] DataByte Byte to send through the USART SPI interface. + * + * \return Response byte from the attached SPI device. + */ + static inline uint8_t SerialSPI_TransferByte(USART_t* const USART, + const uint8_t DataByte) + { + USART->DATA = DataByte; + while (!(USART->STATUS & USART_TXCIF_bm)); + USART->STATUS = USART_TXCIF_bm; + return USART->DATA; + } + + /** Sends a byte through the USART SPI interface, blocking until the transfer is complete. The response + * byte sent to from the attached SPI device is ignored. + * + * \param[in,out] USART Pointer to the base of the USART peripheral within the device. + * \param[in] DataByte Byte to send through the USART SPI interface. + */ + static inline void SerialSPI_SendByte(USART_t* const USART, + const uint8_t DataByte) + { + USART->DATA = DataByte; + while (!(USART->STATUS & USART_TXCIF_bm)); + USART->STATUS = USART_TXCIF_bm; + } + + /** Sends a dummy byte through the USART SPI interface, blocking until the transfer is complete. The response + * byte from the attached SPI device is returned. + * + * \param[in,out] USART Pointer to the base of the USART peripheral within the device. + * + * \return The response byte from the attached SPI device. + */ + static inline uint8_t SerialSPI_ReceiveByte(USART_t* const USART) + { + USART->DATA = 0; + while (!(USART->STATUS & USART_TXCIF_bm)); + USART->STATUS = USART_TXCIF_bm; + return USART->DATA; + } + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */ +