From f45d60f768f438502910fd9fe7cac094c05bca74 Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Sun, 12 Feb 2012 11:48:24 +0000
Subject: Added Serial USART peripheral driver for the XMEGA platform.

Fix XMEGA SPI peripheral driver's incorrect const-ness on the SPI peripheral struct.
---
 LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h    |  24 +--
 LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c |  94 +++++++++
 LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h | 277 +++++++++++++++++++++++++++
 3 files changed, 383 insertions(+), 12 deletions(-)
 create mode 100644 LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c
 create mode 100644 LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h

(limited to 'LUFA/Drivers/Peripheral/XMEGA')

diff --git a/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h b/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h
index e1d77c4e7..1d28d309d 100644
--- a/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h
+++ b/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h
@@ -163,7 +163,7 @@
 			 *  \param[in]      SPIOptions  SPI Options, a mask consisting of one of each of the \c SPI_SPEED_*,
 			 *                         \c SPI_SCK_*, \c SPI_SAMPLE_*, \c SPI_ORDER_* and \c SPI_MODE_* masks.
 			 */
-			static inline void SPI_Init(const SPI_t* SPI,
+			static inline void SPI_Init(SPI_t* const SPI,
 			                            const uint8_t SPIOptions)
 			{
 				SPI->CTRL = (SPIOptions | SPI_ENABLE_bm);
@@ -171,21 +171,21 @@
 
 			/** Turns off the SPI driver, disabling and returning used hardware to their default configuration.
 			 *
-			 *  \param[in, out] SPI Pointer to the base of the SPI peripheral within the device.
+			 *  \param[in, out] SPI   Pointer to the base of the SPI peripheral within the device.
 			 */
-			static inline void SPI_Disable(const SPI_t* SPI)
+			static inline void SPI_Disable(SPI_t* const SPI)
 			{
 				SPI->CTRL &= ~SPI_ENABLE_bm;
 			}
 
 			/** Retrieves the currently selected SPI mode, once the SPI interface has been configured.
 			 *
-			 *  \param[in, out] SPI         Pointer to the base of the SPI peripheral within the device.
+			 *  \param[in, out] SPI  Pointer to the base of the SPI peripheral within the device.
 			 *
 			 *  \return \ref SPI_MODE_MASTER if the interface is currently in SPI Master mode, \ref SPI_MODE_SLAVE otherwise
 			 */
-			static inline uint8_t SPI_GetCurrentMode(const SPI_t* SPI) ATTR_ALWAYS_INLINE;
-			static inline uint8_t SPI_GetCurrentMode(const SPI_t* SPI)
+			static inline uint8_t SPI_GetCurrentMode(SPI_t* const SPI) ATTR_ALWAYS_INLINE;
+			static inline uint8_t SPI_GetCurrentMode(SPI_t* const SPI)
 			{
 				return (SPI->CTRL & SPI_MASTER_bm);
 			}
@@ -197,9 +197,9 @@
 			 *
 			 *  \return Response byte from the attached SPI device.
 			 */
-			static inline uint8_t SPI_TransferByte(const SPI_t* SPI,
+			static inline uint8_t SPI_TransferByte(SPI_t* const SPI,
 			                                       const uint8_t Byte) ATTR_ALWAYS_INLINE;
-			static inline uint8_t SPI_TransferByte(const SPI_t* SPI,
+			static inline uint8_t SPI_TransferByte(SPI_t* const SPI,
 			                                       const uint8_t Byte)
 			{
 				SPI->DATA = Byte;
@@ -213,9 +213,9 @@
 			 *  \param[in, out] SPI   Pointer to the base of the SPI peripheral within the device.
 			 *  \param[in]      Byte  Byte to send through the SPI interface.
 			 */
-			static inline void SPI_SendByte(const SPI_t* SPI,
+			static inline void SPI_SendByte(SPI_t* const SPI,
 			                                const uint8_t Byte) ATTR_ALWAYS_INLINE;
-			static inline void SPI_SendByte(const SPI_t* SPI,
+			static inline void SPI_SendByte(SPI_t* const SPI,
 			                                const uint8_t Byte)
 			{
 				SPI->DATA = Byte;
@@ -229,8 +229,8 @@
 			 *
 			 *  \return The response byte from the attached SPI device.
 			 */
-			static inline uint8_t SPI_ReceiveByte(const SPI_t* SPI) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
-			static inline uint8_t SPI_ReceiveByte(const SPI_t* SPI)
+			static inline uint8_t SPI_ReceiveByte(SPI_t* const SPI) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+			static inline uint8_t SPI_ReceiveByte(SPI_t* const SPI)
 			{
 				SPI->DATA = 0;
 				while (!(SPI->STATUS & SPI_IF_bm));
diff --git a/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c b/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c
new file mode 100644
index 000000000..2f318055f
--- /dev/null
+++ b/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c
@@ -0,0 +1,94 @@
+/*
+             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.
+*/
+
+#define  __INCLUDE_FROM_SERIAL_C
+#include "../Serial.h"
+
+FILE USARTSerialStream;
+
+int Serial_putchar(char DataByte,
+                   FILE *Stream)
+{
+	USART_t* USART = fdev_get_udata(Stream);
+
+	Serial_SendByte(USART, DataByte);
+	return 0;
+}
+
+int Serial_getchar(FILE *Stream)
+{
+	USART_t* USART = fdev_get_udata(Stream);
+
+	if (!(Serial_IsCharReceived(USART)))
+	  return _FDEV_EOF;
+
+	return Serial_ReceiveByte(USART);
+}
+
+int Serial_getchar_Blocking(FILE *Stream)
+{
+	USART_t* USART = fdev_get_udata(Stream);
+
+	while (!(Serial_IsCharReceived(USART)));
+	return Serial_ReceiveByte(USART);
+}
+
+void Serial_SendString_P(USART_t* const USART,
+                         const char* FlashStringPtr)
+{
+	uint8_t CurrByte;
+
+	while ((CurrByte = pgm_read_byte(FlashStringPtr)) != 0x00)
+	{
+		Serial_SendByte(USART, CurrByte);
+		FlashStringPtr++;
+	}
+}
+
+void Serial_SendString(USART_t* const USART,
+                       const char* StringPtr)
+{
+	uint8_t CurrByte;
+
+	while ((CurrByte = *StringPtr) != 0x00)
+	{
+		Serial_SendByte(USART, CurrByte);
+		StringPtr++;
+	}
+}
+
+void Serial_SendData(USART_t* const USART,
+                     const uint8_t* Buffer,
+                     uint16_t Length)
+{
+	while (Length--)
+	  Serial_SendByte(USART, *(Buffer++));
+}
+
diff --git a/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h b/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h
new file mode 100644
index 000000000..50352195c
--- /dev/null
+++ b/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h
@@ -0,0 +1,277 @@
+/*
+             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 Peripheral Driver (XMEGA)
+ *
+ *  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 USART driver
+ *        dispatch header located in LUFA/Drivers/Peripheral/Serial.h.
+ */
+
+/** \ingroup Group_Serial
+ *  \defgroup Group_Serial_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/Serial.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 serial USART driver before first use, with 9600 baud (and no double-speed mode)
+ *      Serial_Init(9600, false);
+ *
+ *      // Send a string through the USART
+ *      Serial_TxString("Test String\r\n");
+ *
+ *      // Receive a byte through the USART
+ *      uint8_t DataByte = Serial_RxByte();
+ *  \endcode
+ *
+ *  @{
+ */
+
+#ifndef __SERIAL_XMEGA_H__
+#define __SERIAL_XMEGA_H__
+
+	/* Includes: */
+		#include "../../../Common/Common.h"
+		#include "../../Misc/TerminalCodes.h"
+
+		#include <stdio.h>
+
+	/* Enable C linkage for C++ Compilers: */
+		#if defined(__cplusplus)
+			extern "C" {
+		#endif
+
+	/* Preprocessor Checks: */
+		#if !defined(__INCLUDE_FROM_SERIAL_H) && !defined(__INCLUDE_FROM_SERIAL_C)
+			#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__)
+		/* External Variables: */
+			extern FILE USARTSerialStream;
+
+		/* Function Prototypes: */
+			int Serial_putchar(char DataByte,
+			                   FILE *Stream);
+			int Serial_getchar(FILE *Stream);
+			int Serial_getchar_Blocking(FILE *Stream);
+	#endif
+
+	/* Public Interface - May be used in end-application: */
+		/* Macros: */
+			/** Macro for calculating the baud value from a given baud rate when the \c U2X (double speed) bit is
+			 *  not set.
+			 *
+			 *  \param[in] Baud  Target serial UART baud rate.
+			 *
+			 *  \return Closest UBRR register value for the given UART frequency.
+			 */
+			#define SERIAL_UBBRVAL(Baud)    ((((F_CPU / 16) + (Baud / 2)) / (Baud)) - 1)
+
+			/** Macro for calculating the baud value from a given baud rate when the \c U2X (double speed) bit is
+			 *  set.
+			 *
+			 *  \param[in] Baud  Target serial UART baud rate.
+			 *
+			 *  \return Closest UBRR register value for the given UART frequency.
+			 */
+			#define SERIAL_2X_UBBRVAL(Baud) ((((F_CPU / 8) + (Baud / 2)) / (Baud)) - 1)
+
+		/* Function Prototypes: */
+			/** Transmits a given string located in program space (FLASH) through the USART.
+			 *
+			 *  \param[in,out] USART           Pointer to the base of the USART peripheral within the device.
+			 *  \param[in]     FlashStringPtr  Pointer to a string located in program space.
+			 */
+			void Serial_SendString_P(USART_t* const USART,
+			                         const char* FlashStringPtr) ATTR_NON_NULL_PTR_ARG(1);
+
+			/** Transmits a given string located in SRAM memory through the USART.
+			 *
+			 *  \param[in,out] USART      Pointer to the base of the USART peripheral within the device.
+			 *  \param[in]     StringPtr  Pointer to a string located in SRAM space.
+			 */
+			void Serial_SendString(USART_t* const USART,
+			                       const char* StringPtr) ATTR_NON_NULL_PTR_ARG(1);
+
+			/** Transmits a given buffer located in SRAM memory through the USART.
+			 *
+			 *  \param[in,out] USART   Pointer to the base of the USART peripheral within the device.
+			 *  \param[in]     Buffer  Pointer to a buffer containing the data to send.
+			 *  \param[in]     Length  Length of the data to send, in bytes.
+			 */
+			void Serial_SendData(USART_t* const USART,
+			                     const uint8_t* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+		/* Inline Functions: */
+			/** Initializes the USART, ready for serial data transmission and reception. This initializes the interface to
+			 *  standard 8-bit, no parity, 1 stop bit settings suitable for most applications.
+			 *
+			 *  \param[in,out] USART        Pointer to the base of the USART peripheral within the device.
+			 *  \param[in]     BaudRate     Serial baud rate, in bits per second.
+			 *  \param[in]     DoubleSpeed  Enables double speed mode when set, halving the sample time to double the baud rate.
+			 */
+			static inline void Serial_Init(USART_t* const USART,
+			                               const uint32_t BaudRate,
+			                               const bool DoubleSpeed)
+			{
+				uint32_t BaudValue = (DoubleSpeed ? SERIAL_2X_UBBRVAL(BaudRate) : SERIAL_UBBRVAL(BaudRate));
+
+				USART->BAUDCTRLB = (BaudValue >> 8);
+				USART->BAUDCTRLA = (BaudValue & 0xFF);
+				
+				USART->CTRLC = (USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc);
+				USART->CTRLB = (USART_RXEN_bm | USART_TXEN_bm | (DoubleSpeed ? USART_CLK2X_bm : 0));
+			}
+
+			/** 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 Serial_Disable(USART_t* const USART)
+			{
+				USART->CTRLA = 0;
+				USART->CTRLB = 0;
+				USART->CTRLC = 0;
+			}
+
+			/** Creates a standard character stream from the USART so that it can be used with all the regular functions
+			 *  in the avr-libc \c <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf). The created
+			 *  stream is bidirectional and can be used for both input and output functions.
+			 *
+			 *  Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
+			 *  fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
+			 *  be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own
+			 *  line buffering.
+			 *
+			 *  \param[in,out] USART   Pointer to the base of the USART peripheral within the device.
+			 *  \param[in,out] Stream  Pointer to a FILE structure where the created stream should be placed, if \c NULL, \c stdout
+			 *                         and \c stdin will be configured to use the USART.
+			 *
+			 *  \pre The USART must first be configured via a call to \ref Serial_Init() before the stream is used.
+			 */
+			static inline void Serial_CreateStream(USART_t* const USART,
+			                                       FILE* Stream)
+			{
+				if (!(Stream))
+				{
+					Stream = &USARTSerialStream;
+					stdin  = Stream;
+					stdout = Stream;
+				}
+
+				*Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar, _FDEV_SETUP_RW);
+				fdev_set_udata(Stream, USART);
+			}
+
+			/** Identical to \ref Serial_CreateStream(), except that reads are blocking until the calling stream function terminates
+			 *  the transfer.
+			 *
+			 *  \param[in,out] USART   Pointer to the base of the USART peripheral within the device.
+			 *  \param[in,out] Stream  Pointer to a FILE structure where the created stream should be placed, if \c NULL, \c stdout
+			 *                         and \c stdin will be configured to use the USART.
+			 *
+			 *  \pre The USART must first be configured via a call to \ref Serial_Init() before the stream is used.
+			 */
+			static inline void Serial_CreateBlockingStream(USART_t* const USART,
+			                                               FILE* Stream)
+			{
+				if (!(Stream))
+				{
+					Stream = &USARTSerialStream;
+					stdin  = Stream;
+					stdout = Stream;
+				}
+
+				*Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar_Blocking, _FDEV_SETUP_RW);
+				fdev_set_udata(Stream, USART);
+			}
+
+			/** Indicates whether a character has been received through the USART.
+			 *
+			 *  \param[in,out] USART  Pointer to the base of the USART peripheral within the device.
+			 *
+			 *  \return Boolean \c true if a character has been received, \c false otherwise.
+			 */
+			static inline bool Serial_IsCharReceived(USART_t* const USART) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+			static inline bool Serial_IsCharReceived(USART_t* const USART)
+			{
+				return ((USART->STATUS & USART_RXCIF_bm) ? true : false);
+			}
+
+			/** Transmits a given byte through the USART.
+			 *
+			 *  \param[in,out] USART     Pointer to the base of the USART peripheral within the device.
+			 *  \param[in]     DataByte  Byte to transmit through the USART.
+			 */
+			static inline void Serial_SendByte(USART_t* const USART,
+			                                   const char DataByte) ATTR_ALWAYS_INLINE;
+			static inline void Serial_SendByte(USART_t* const USART,
+			                                   const char DataByte)
+			{
+				while (!(USART->STATUS & USART_DREIF_bm));
+				USART->DATA = DataByte;
+			}
+
+			/** Receives the next byte from the USART.
+			 *
+			 *  \param[in,out] USART  Pointer to the base of the USART peripheral within the device.
+			 *
+			 *  \return Next byte received from the USART, or a negative value if no byte has been received.
+			 */
+			static inline int16_t Serial_ReceiveByte(USART_t* const USART) ATTR_ALWAYS_INLINE;
+			static inline int16_t Serial_ReceiveByte(USART_t* const USART)
+			{
+				if (!(Serial_IsCharReceived(USART)))
+				  return -1;
+
+				return USART->DATA;
+			}
+
+	/* Disable C linkage for C++ Compilers: */
+		#if defined(__cplusplus)
+			}
+		#endif
+
+#endif
+
+/** @} */
+
-- 
cgit v1.2.3