1
0
Fork 0

Squashed 'tmk_core/' changes from caca2c0..dc0e46e

dc0e46e Rename LUFA to LUFA-git
3bfa7fa Remove LUFA-120730
215b764 Merge commit 'afa0f22a9299686fd88f58ce09c5b521ac917e8f' as 'protocol/lufa/LUFA'
afa0f22 Squashed 'protocol/lufa/LUFA/' content from commit def7fca
c0c42fa Remove submodule of LUFA
30f897d Merge commit '87ced33feb74e79c3281dda36eb6d6d153399b41' as 'protocol/usb_hid/USB_Host_Shield_2.0'
87ced33 Squashed 'protocol/usb_hid/USB_Host_Shield_2.0/' content from commit aab4a69
14f6d49 Remove submodule of USB_Host_Shield_2.0

git-subtree-dir: tmk_core
git-subtree-split: dc0e46eaa4367d4e218f8816e3c117895820f07c
This commit is contained in:
tmk 2015-05-13 11:13:10 +09:00
parent 4d116a04e9
commit f6d56675f9
1575 changed files with 421901 additions and 63190 deletions

View file

@ -0,0 +1,75 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Analogue-to-Digital converter driver.
*
* This file is the master dispatch header file for the device-specific ADC driver, for microcontrollers
* containing an ADC.
*
* 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_ADC ADC Driver - LUFA/Drivers/Peripheral/ADC.h
* \brief Hardware Analogue-to-Digital converter driver.
*
* \section Sec_ADC_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - None
*
* \section Sec_ADC_ModDescription Module Description
* Hardware ADC driver. This module provides an easy to use driver for the hardware ADC
* present on many microcontrollers, for the conversion of analogue signals into the
* digital domain.
*
* \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 __ADC_H__
#define __ADC_H__
/* Macros: */
#define __INCLUDE_FROM_ADC_H
/* Includes: */
#include "../../Common/Common.h"
/* Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/ADC_AVR8.h"
#else
#error The ADC peripheral driver is not currently available for your selected architecture.
#endif
#endif

View file

@ -0,0 +1,446 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 ADC Peripheral Driver (AVR8)
*
* On-chip Analogue-to-Digital converter (ADC) driver for supported U4, U6 and U7 model AVRs that contain an ADC
* peripheral internally.
*
* \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/ADC.h.
*/
/** \ingroup Group_ADC
* \defgroup Group_ADC_AVR8 ADC Peripheral Driver (AVR8)
*
* \section Sec_ADC_AVR8_ModDescription Module Description
* On-chip Analogue-to-Digital converter (ADC) driver for supported U4, U6 and U7 model AVRs that contain an ADC
* peripheral internally.
*
* \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/ADC.h.
*
* \section Sec_ADC_AVR8_ExampleUsage Example Usage
* The following snippet is an example of how this module may be used within a typical
* application.
*
* \code
* // Initialize the ADC driver before first use
* ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_32);
*
* // Must setup the ADC channel to read beforehand
* ADC_SetupChannel(1);
*
* // Perform a single conversion of the ADC channel 1
* ADC_GetChannelReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | ADC_CHANNEL1);
* printf("Conversion Result: %d\r\n", ADC_GetResult());
*
* // Start reading ADC channel 1 in free running (continuous conversion) mode
* ADC_StartReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | ADC_CHANNEL1);
* for (;;)
* {
* while (!(ADC_IsReadingComplete())) {};
* printf("Conversion Result: %d\r\n", ADC_GetResult());
* }
* \endcode
*
* @{
*/
#ifndef __ADC_AVR8_H__
#define __ADC_AVR8_H__
/* Includes: */
#include "../../../Common/Common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_ADC_H)
#error Do not include this file directly. Include LUFA/Drivers/Peripheral/ADC.h instead.
#endif
#if !(defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \
defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
#error The ADC peripheral driver is not currently available for your selected microcontroller model.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name ADC Reference Configuration Masks */
//@{
/** Reference mask, for using the voltage present at the AVR's AREF pin for the ADC reference. */
#define ADC_REFERENCE_AREF 0
/** Reference mask, for using the voltage present at the AVR's AVCC pin for the ADC reference. */
#define ADC_REFERENCE_AVCC (1 << REFS0)
/** Reference mask, for using the internally generated 2.56V reference voltage as the ADC reference. */
#define ADC_REFERENCE_INT2560MV ((1 << REFS1) | (1 << REFS0))
//@}
/** \name ADC Result Adjustment Configuration Masks */
//@{
/** Left-adjusts the 10-bit ADC result, so that the upper 8 bits of the value returned by the
* \ref ADC_GetResult() macro contain the 8 most significant bits of the result.
*/
#define ADC_LEFT_ADJUSTED (1 << ADLAR)
/** Right-adjusts the 10-bit ADC result, so that the lower 8 bits of the value returned by the
* \ref ADC_GetResult() macro contain the 8 least significant bits of the result.
*/
#define ADC_RIGHT_ADJUSTED (0 << ADLAR)
//@}
/** \name ADC Mode Configuration Masks */
//@{
/** Sets the ADC mode to free running, so that conversions take place continuously as fast as the ADC
* is capable of at the given input clock speed.
*/
#define ADC_FREE_RUNNING (1 << ADATE)
/** Sets the ADC mode to single conversion, so that only a single conversion will take place before
* the ADC returns to idle.
*/
#define ADC_SINGLE_CONVERSION (0 << ADATE)
//@}
/** \name ADC Prescaler Configuration Masks */
//@{
/** Sets the ADC input clock to prescale by a factor of 2 the AVR's system clock. */
#define ADC_PRESCALE_2 (1 << ADPS0)
/** Sets the ADC input clock to prescale by a factor of 4 the AVR's system clock. */
#define ADC_PRESCALE_4 (1 << ADPS1)
/** Sets the ADC input clock to prescale by a factor of 8 the AVR's system clock. */
#define ADC_PRESCALE_8 ((1 << ADPS0) | (1 << ADPS1))
/** Sets the ADC input clock to prescale by a factor of 16 the AVR's system clock. */
#define ADC_PRESCALE_16 (1 << ADPS2)
/** Sets the ADC input clock to prescale by a factor of 32 the AVR's system clock. */
#define ADC_PRESCALE_32 ((1 << ADPS2) | (1 << ADPS0))
/** Sets the ADC input clock to prescale by a factor of 64 the AVR's system clock. */
#define ADC_PRESCALE_64 ((1 << ADPS2) | (1 << ADPS1))
/** Sets the ADC input clock to prescale by a factor of 128 the AVR's system clock. */
#define ADC_PRESCALE_128 ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0))
//@}
/** \name ADC MUX Masks */
//@{
/** MUX mask define for the ADC0 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
#define ADC_CHANNEL0 (0x00 << MUX0)
/** MUX mask define for the ADC1 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
#define ADC_CHANNEL1 (0x01 << MUX0)
#if (!(defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) || defined(__DOXYGEN__))
/** MUX mask define for the ADC2 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_CHANNEL2 (0x02 << MUX0)
/** MUX mask define for the ADC3 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_CHANNEL3 (0x03 << MUX0)
#endif
/** MUX mask define for the ADC4 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
#define ADC_CHANNEL4 (0x04 << MUX0)
/** MUX mask define for the ADC5 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
#define ADC_CHANNEL5 (0x05 << MUX0)
/** MUX mask define for the ADC6 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
#define ADC_CHANNEL6 (0x06 << MUX0)
/** MUX mask define for the ADC7 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */
#define ADC_CHANNEL7 (0x07 << MUX0)
#if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__DOXYGEN__))
/** MUX mask define for the ADC8 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_CHANNEL8 ((1 << 8) | (0x00 << MUX0))
/** MUX mask define for the ADC9 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_CHANNEL9 ((1 << 8) | (0x01 << MUX0))
/** MUX mask define for the ADC10 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_CHANNEL10 ((1 << 8) | (0x02 << MUX0))
/** MUX mask define for the ADC11 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_CHANNEL11 ((1 << 8) | (0x03 << MUX0))
/** MUX mask define for the ADC12 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_CHANNEL12 ((1 << 8) | (0x04 << MUX0))
/** MUX mask define for the ADC13 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_CHANNEL13 ((1 << 8) | (0x05 << MUX0))
/** MUX mask define for the internal temperature sensor channel of the ADC. See \ref ADC_StartReading() and
* \ref ADC_GetChannelReading().
*
* \note Not available on all AVR models.
*/
#define ADC_INT_TEMP_SENS ((1 << 8) | (0x07 << MUX0))
#endif
/** MUX mask define for the internal 1.1V band-gap channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
#define ADC_1100MV_BANDGAP (0x1E << MUX0)
/** Retrieves the ADC MUX mask for the given ADC channel number.
*
* \attention This macro will only work correctly on channel numbers that are compile-time
* constants defined by the preprocessor.
*
* \param[in] Channel Index of the ADC channel whose MUX mask is to be retrieved.
*/
#define ADC_GET_CHANNEL_MASK(Channel) CONCAT_EXPANDED(ADC_CHANNEL, Channel)
//@}
/* Inline Functions: */
/** Configures the given ADC channel, ready for ADC conversions. This function sets the
* associated port pin as an input and disables the digital portion of the I/O to reduce
* power consumption.
*
* \note This must only be called for ADC channels with are connected to a physical port
* pin of the AVR, denoted by its special alternative function ADCx.
*
* \warning The channel number must be specified as an integer, and <b>not</b> a \c ADC_CHANNEL* mask.
*
* \param[in] ChannelIndex ADC channel number to set up for conversions.
*/
static inline void ADC_SetupChannel(const uint8_t ChannelIndex)
{
#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__))
DDRF &= ~(1 << ChannelIndex);
DIDR0 |= (1 << ChannelIndex);
#elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
if (ChannelIndex < 8)
{
DDRF &= ~(1 << ChannelIndex);
DIDR0 |= (1 << ChannelIndex);
}
else if (ChannelIndex == 8)
{
DDRD &= ~(1 << 4);
DIDR2 |= (1 << 0);
}
else if (ChannelIndex < 11)
{
DDRD &= ~(1 << (ChannelIndex - 3));
DIDR2 |= (1 << (ChannelIndex - 8));
}
else
{
DDRB &= ~(1 << (ChannelIndex - 7));
DIDR2 |= (1 << (ChannelIndex - 8));
}
#endif
}
/** De-configures the given ADC channel, re-enabling digital I/O mode instead of analog. This
* function sets the associated port pin as an input and re-enabled the digital portion of
* the I/O.
*
* \note This must only be called for ADC channels with are connected to a physical port
* pin of the AVR, denoted by its special alternative function ADCx.
*
* \warning The channel number must be specified as an integer, and <b>not</b> a \c ADC_CHANNEL* mask.
*
* \param[in] ChannelIndex ADC channel number to set up for conversions.
*/
static inline void ADC_DisableChannel(const uint8_t ChannelIndex)
{
#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__))
DDRF &= ~(1 << ChannelIndex);
DIDR0 &= ~(1 << ChannelIndex);
#elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
if (ChannelIndex < 8)
{
DDRF &= ~(1 << ChannelIndex);
DIDR0 &= ~(1 << ChannelIndex);
}
else if (ChannelIndex == 8)
{
DDRD &= ~(1 << 4);
DIDR2 &= ~(1 << 0);
}
else if (ChannelIndex < 11)
{
DDRD &= ~(1 << (ChannelIndex - 3));
DIDR2 &= ~(1 << (ChannelIndex - 8));
}
else
{
DDRB &= ~(1 << (ChannelIndex - 7));
DIDR2 &= ~(1 << (ChannelIndex - 8));
}
#endif
}
/** Starts the reading of the given channel, but does not wait until the conversion has completed.
* Once executed, the conversion status can be determined via the \ref ADC_IsReadingComplete() macro and
* the result read via the \ref ADC_GetResult() macro.
*
* If the ADC has been initialized in free running mode, calling this function once will begin the repeated
* conversions. If the ADC is in single conversion mode (or the channel to convert from is to be changed),
* this function must be called each time a conversion is to take place.
*
* \param[in] MUXMask ADC channel mask, reference mask and adjustment mask.
*/
static inline void ADC_StartReading(const uint16_t MUXMask)
{
ADMUX = MUXMask;
#if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__DOXYGEN__))
if (MUXMask & (1 << 8))
ADCSRB |= (1 << MUX5);
else
ADCSRB &= ~(1 << MUX5);
#endif
ADCSRA |= (1 << ADSC);
}
/** Indicates if the current ADC conversion is completed, or still in progress.
*
* \return Boolean \c 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.
*
* \note For free running mode, the automated conversions should be initialized with a single call
* to \ref ADC_StartReading() to select the channel and begin the automated conversions, and
* the results read directly from the \ref ADC_GetResult() instead to reduce overhead.
*
* \param[in] MUXMask Mask comprising of an ADC channel mask, reference mask and adjustment mask.
*
* \return Converted ADC result for the given ADC channel.
*/
static inline uint16_t ADC_GetChannelReading(const uint16_t MUXMask) ATTR_WARN_UNUSED_RESULT;
static inline uint16_t ADC_GetChannelReading(const uint16_t MUXMask)
{
ADC_StartReading(MUXMask);
while (!(ADC_IsReadingComplete()));
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 prescale and mode settings.
*/
static inline void ADC_Init(const uint8_t Mode) ATTR_ALWAYS_INLINE;
static inline void ADC_Init(const 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_Disable(void) ATTR_ALWAYS_INLINE;
static inline void ADC_Disable(void)
{
ADCSRA = 0;
}
/** Indicates if the ADC is currently enabled.
*
* \return Boolean \c true if the ADC subsystem is currently enabled, \c 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)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,258 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 SPI Peripheral Driver (AVR8)
*
* On-chip SPI driver for the 8-bit AVR microcontrollers.
*
* \note This file should not be included directly. It is automatically included as needed by the SPI driver
* dispatch header located in LUFA/Drivers/Peripheral/SPI.h.
*/
/** \ingroup Group_SPI
* \defgroup Group_SPI_AVR8 SPI Peripheral Driver (AVR8)
*
* \section Sec_SPI_AVR8_ModDescription Module Description
* Driver for the hardware SPI port available on most 8-bit AVR microcontroller models. This
* module provides an easy to use driver for the setup and transfer of data over the
* AVR's SPI port.
*
* \note This file should not be included directly. It is automatically included as needed by the SPI driver
* dispatch header located in LUFA/Drivers/Peripheral/SPI.h.
*
* \section Sec_SPI_AVR8_ExampleUsage Example Usage
* The following snippet is an example of how this module may be used within a typical
* application.
*
* \code
* // Initialize the SPI driver before first use
* SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING |
* SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
*
* // Send several bytes, ignoring the returned data
* SPI_SendByte(0x01);
* SPI_SendByte(0x02);
* SPI_SendByte(0x03);
*
* // Receive several bytes, sending a dummy 0x00 byte each time
* uint8_t Byte1 = SPI_ReceiveByte();
* uint8_t Byte2 = SPI_ReceiveByte();
* uint8_t Byte3 = SPI_ReceiveByte();
*
* // Send a byte, and store the received byte from the same transaction
* uint8_t ResponseByte = SPI_TransferByte(0xDC);
* \endcode
*
* @{
*/
#ifndef __SPI_AVR8_H__
#define __SPI_AVR8_H__
/* Includes: */
#include "../../../Common/Common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_SPI_H)
#error Do not include this file directly. Include LUFA/Drivers/Peripheral/SPI.h instead.
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define SPI_USE_DOUBLESPEED (1 << SPE)
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name SPI Prescaler Configuration Masks */
//@{
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 2. */
#define SPI_SPEED_FCPU_DIV_2 SPI_USE_DOUBLESPEED
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 4. */
#define SPI_SPEED_FCPU_DIV_4 0
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 8. */
#define SPI_SPEED_FCPU_DIV_8 (SPI_USE_DOUBLESPEED | (1 << SPR0))
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 16. */
#define SPI_SPEED_FCPU_DIV_16 (1 << SPR0)
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 32. */
#define SPI_SPEED_FCPU_DIV_32 (SPI_USE_DOUBLESPEED | (1 << SPR1))
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 64. */
#define SPI_SPEED_FCPU_DIV_64 (SPI_USE_DOUBLESPEED | (1 << SPR1) | (1 << SPR0))
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 128. */
#define SPI_SPEED_FCPU_DIV_128 ((1 << SPR1) | (1 << SPR0))
//@}
/** \name SPI SCK Polarity Configuration Masks */
//@{
/** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the rising edge. */
#define SPI_SCK_LEAD_RISING (0 << CPOL)
/** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the falling edge. */
#define SPI_SCK_LEAD_FALLING (1 << CPOL)
//@}
/** \name SPI Sample Edge Configuration Masks */
//@{
/** SPI data sample mode mask for \ref SPI_Init(). Indicates that the data should sampled on the leading edge. */
#define SPI_SAMPLE_LEADING (0 << CPHA)
/** SPI data sample mode mask for \ref SPI_Init(). Indicates that the data should be sampled on the trailing edge. */
#define SPI_SAMPLE_TRAILING (1 << CPHA)
//@}
/** \name SPI Data Ordering Configuration Masks */
//@{
/** SPI data order mask for \ref SPI_Init(). Indicates that data should be shifted out MSB first. */
#define SPI_ORDER_MSB_FIRST (0 << DORD)
/** SPI data order mask for \ref SPI_Init(). Indicates that data should be shifted out LSB first. */
#define SPI_ORDER_LSB_FIRST (1 << DORD)
//@}
/** \name SPI Mode Configuration Masks */
//@{
/** SPI mode mask for \ref SPI_Init(). Indicates that the SPI interface should be initialized into slave mode. */
#define SPI_MODE_SLAVE (0 << MSTR)
/** SPI mode mask for \ref SPI_Init(). Indicates that the SPI interface should be initialized into master mode. */
#define SPI_MODE_MASTER (1 << MSTR)
//@}
/* Inline Functions: */
/** Initializes the SPI subsystem, ready for transfers. Must be called before calling any other
* SPI routines.
*
* \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 uint8_t SPIOptions);
static inline void SPI_Init(const uint8_t SPIOptions)
{
/* Prevent high rise times on PB.0 (/SS) from forcing a change to SPI slave mode */
DDRB |= (1 << 0);
PORTB |= (1 << 0);
DDRB |= ((1 << 1) | (1 << 2));
DDRB &= ~(1 << 3);
PORTB |= (1 << 3);
if (SPIOptions & SPI_USE_DOUBLESPEED)
SPSR |= (1 << SPI2X);
else
SPSR &= ~(1 << SPI2X);
/* Switch /SS to input mode after configuration to allow for forced mode changes */
DDRB &= ~(1 << 0);
SPCR = ((1 << SPE) | SPIOptions);
}
/** Turns off the SPI driver, disabling and returning used hardware to their default configuration. */
static inline void SPI_Disable(void);
static inline void SPI_Disable(void)
{
DDRB &= ~((1 << 1) | (1 << 2));
PORTB &= ~((1 << 0) | (1 << 3));
SPCR = 0;
SPSR = 0;
}
/** Retrieves the currently selected SPI mode, once the SPI interface has been configured.
*
* \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(void) ATTR_ALWAYS_INLINE;
static inline uint8_t SPI_GetCurrentMode(void)
{
return (SPCR & SPI_MODE_MASTER);
}
/** Sends and receives a byte through the SPI interface, blocking until the transfer is complete.
*
* \param[in] Byte Byte to send through the SPI interface.
*
* \return Response byte from the attached SPI device.
*/
static inline uint8_t SPI_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
static inline uint8_t SPI_TransferByte(const uint8_t Byte)
{
SPDR = Byte;
while (!(SPSR & (1 << SPIF)));
return SPDR;
}
/** Sends a byte through the SPI interface, blocking until the transfer is complete. The response
* byte sent to from the attached SPI device is ignored.
*
* \param[in] Byte Byte to send through the SPI interface.
*/
static inline void SPI_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
static inline void SPI_SendByte(const uint8_t Byte)
{
SPDR = Byte;
while (!(SPSR & (1 << SPIF)));
}
/** Sends a dummy byte through the 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 SPI_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
static inline uint8_t SPI_ReceiveByte(void)
{
SPDR = 0x00;
while (!(SPSR & (1 << SPIF)));
return SPDR;
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,208 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master SPI Mode Serial USART 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 Master SPI Mode Serial USART Peripheral Driver (AVR8)
*
* \section Sec_SerialSPI_AVR8_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_SerialSPI_AVR8_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 | USART_SPI_SAMPLE_LEADING | USART_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 <stdio.h>
/* 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)
/* Master USART SPI mode flag definitions missing in the AVR8 toolchain */
#if !defined(UCPHA1)
#define UCPHA1 1
#endif
#if !defined(UDORD1)
#define UDORD1 2
#endif
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name SPI SCK Polarity Configuration Masks */
//@{
/** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the rising edge. */
#define USART_SPI_SCK_LEAD_RISING (0 << UCPOL1)
/** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the falling edge. */
#define USART_SPI_SCK_LEAD_FALLING (1 << UCPOL1)
//@}
/** \name SPI Sample Edge Configuration Masks */
//@{
/** SPI data sample mode mask for \ref SerialSPI_Init(). Indicates that the data should sampled on the leading edge. */
#define USART_SPI_SAMPLE_LEADING (0 << UCPHA1)
/** SPI data sample mode mask for \ref SerialSPI_Init(). Indicates that the data should be sampled on the trailing edge. */
#define USART_SPI_SAMPLE_TRAILING (1 << UCPHA1)
//@}
/** \name SPI Data Ordering Configuration Masks */
//@{
/** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out MSB first. */
#define USART_SPI_ORDER_MSB_FIRST (0 << UDORD1)
/** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out LSB first. */
#define USART_SPI_ORDER_LSB_FIRST (1 << UDORD1)
//@}
/* 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)
{
DDRD |= ((1 << 3) | (1 << 5));
PORTD |= (1 << 2);
UCSR1C = ((1 << UMSEL11) | (1 << UMSEL10) | SPIOptions);
UCSR1B = ((1 << TXEN1) | (1 << RXEN1));
UBRR1 = SERIAL_SPI_UBBRVAL(BaudRate);
}
/** 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) | (1 << 5));
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)
{
SerialSPI_TransferByte(DataByte);
}
/** 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)
{
return SerialSPI_TransferByte(0);
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,119 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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.
*/
#include "../../../Common/Common.h"
#if (ARCH == ARCH_AVR8)
#define __INCLUDE_FROM_SERIAL_C
#include "../Serial.h"
FILE USARTSerialStream;
int Serial_putchar(char DataByte,
FILE *Stream)
{
(void)Stream;
Serial_SendByte(DataByte);
return 0;
}
int Serial_getchar(FILE *Stream)
{
(void)Stream;
if (!(Serial_IsCharReceived()))
return _FDEV_EOF;
return Serial_ReceiveByte();
}
int Serial_getchar_Blocking(FILE *Stream)
{
(void)Stream;
while (!(Serial_IsCharReceived()));
return Serial_ReceiveByte();
}
void Serial_SendString_P(const char* FlashStringPtr)
{
uint8_t CurrByte;
while ((CurrByte = pgm_read_byte(FlashStringPtr)) != 0x00)
{
Serial_SendByte(CurrByte);
FlashStringPtr++;
}
}
void Serial_SendString(const char* StringPtr)
{
uint8_t CurrByte;
while ((CurrByte = *StringPtr) != 0x00)
{
Serial_SendByte(CurrByte);
StringPtr++;
}
}
void Serial_SendData(const void* Buffer,
uint16_t Length)
{
while (Length--)
Serial_SendByte(*((uint8_t*)Buffer++));
}
void Serial_CreateStream(FILE* Stream)
{
if (!(Stream))
{
Stream = &USARTSerialStream;
stdin = Stream;
stdout = Stream;
}
*Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar, _FDEV_SETUP_RW);
}
void Serial_CreateBlockingStream(FILE* Stream)
{
if (!(Stream))
{
Stream = &USARTSerialStream;
stdin = Stream;
stdout = Stream;
}
*Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar_Blocking, _FDEV_SETUP_RW);
}
#endif

View file

@ -0,0 +1,270 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 (AVR8)
*
* On-chip serial USART driver for the 8-bit 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_AVR8 Serial USART Peripheral Driver (AVR8)
*
* \section Sec_Serial_AVR8_ModDescription Module Description
* On-chip serial USART driver for the 8-bit 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.
*
* \section Sec_Serial_AVR8_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_SendString("Test String\r\n");
*
* // Send a raw byte through the USART
* Serial_SendByte(0xDC);
*
* // Receive a byte through the USART (or -1 if no data received)
* int16_t DataByte = Serial_ReceiveByte();
* \endcode
*
* @{
*/
#ifndef __SERIAL_AVR8_H__
#define __SERIAL_AVR8_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 NUL terminated string located in program space (FLASH) through the USART.
*
* \param[in] FlashStringPtr Pointer to a string located in program space.
*/
void Serial_SendString_P(const char* FlashStringPtr) ATTR_NON_NULL_PTR_ARG(1);
/** Transmits a given NUL terminated string located in SRAM memory through the USART.
*
* \param[in] StringPtr Pointer to a string located in SRAM space.
*/
void Serial_SendString(const char* StringPtr) ATTR_NON_NULL_PTR_ARG(1);
/** Transmits a given buffer located in SRAM memory through the USART.
*
* \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(const void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** 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] 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.
*/
void Serial_CreateStream(FILE* Stream);
/** Identical to \ref Serial_CreateStream(), except that reads are blocking until the calling stream function terminates
* the transfer.
*
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL, \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.
*/
void Serial_CreateBlockingStream(FILE* Stream);
/* 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] 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(const uint32_t BaudRate,
const bool DoubleSpeed);
static inline void Serial_Init(const uint32_t BaudRate,
const bool DoubleSpeed)
{
UBRR1 = (DoubleSpeed ? SERIAL_2X_UBBRVAL(BaudRate) : SERIAL_UBBRVAL(BaudRate));
UCSR1C = ((1 << UCSZ11) | (1 << UCSZ10));
UCSR1A = (DoubleSpeed ? (1 << U2X1) : 0);
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 Serial_Disable(void);
static inline void Serial_Disable(void)
{
UCSR1B = 0;
UCSR1A = 0;
UCSR1C = 0;
UBRR1 = 0;
DDRD &= ~(1 << 3);
PORTD &= ~(1 << 2);
}
/** Indicates whether a character has been received through the USART.
*
* \return Boolean \c true if a character has been received, \c 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);
}
/** Indicates whether there is hardware buffer space for a new transmit on the USART. This
* function can be used to determine if a call to \ref Serial_SendByte() will block in advance.
*
* \return Boolean \c true if a character can be queued for transmission immediately, \c false otherwise.
*/
static inline bool Serial_IsSendReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Serial_IsSendReady(void)
{
return ((UCSR1A & (1 << UDRE1)) ? true : false);
}
/** Indicates whether the hardware USART transmit buffer is completely empty, indicating all
* pending transmissions have completed.
*
* \return Boolean \c true if no characters are buffered for transmission, \c false otherwise.
*/
static inline bool Serial_IsSendComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
static inline bool Serial_IsSendComplete(void)
{
return ((UCSR1A & (1 << TXC1)) ? true : false);
}
/** Transmits a given byte through the USART.
*
* \note If no buffer space is available in the hardware USART, this function will block. To check if
* space is available before calling this function, see \ref Serial_IsSendReady().
*
* \param[in] DataByte Byte to transmit through the USART.
*/
static inline void Serial_SendByte(const char DataByte) ATTR_ALWAYS_INLINE;
static inline void Serial_SendByte(const char DataByte)
{
while (!(Serial_IsSendReady()));
UDR1 = DataByte;
}
/** Receives the next byte from the USART.
*
* \return Next byte received from the USART, or a negative value if no byte has been received.
*/
static inline int16_t Serial_ReceiveByte(void) ATTR_ALWAYS_INLINE;
static inline int16_t Serial_ReceiveByte(void)
{
if (!(Serial_IsCharReceived()))
return -1;
return UDR1;
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,209 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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.
*/
#include "../../../Common/Common.h"
#if (ARCH == ARCH_AVR8) && defined(TWCR)
#define __INCLUDE_FROM_TWI_C
#include "../TWI.h"
uint8_t TWI_StartTransmission(const uint8_t SlaveAddress,
const uint8_t TimeoutMS)
{
for (;;)
{
bool BusCaptured = false;
uint16_t TimeoutRemaining;
TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
TimeoutRemaining = (TimeoutMS * 100);
while (TimeoutRemaining && !(BusCaptured))
{
if (TWCR & (1 << TWINT))
{
switch (TWSR & TW_STATUS_MASK)
{
case TW_START:
case TW_REP_START:
BusCaptured = true;
break;
case TW_MT_ARB_LOST:
TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
continue;
default:
TWCR = (1 << TWEN);
return TWI_ERROR_BusFault;
}
}
_delay_us(10);
TimeoutRemaining--;
}
if (!(TimeoutRemaining))
{
TWCR = (1 << TWEN);
return TWI_ERROR_BusCaptureTimeout;
}
TWDR = SlaveAddress;
TWCR = ((1 << TWINT) | (1 << TWEN));
TimeoutRemaining = (TimeoutMS * 100);
while (TimeoutRemaining)
{
if (TWCR & (1 << TWINT))
break;
_delay_us(10);
TimeoutRemaining--;
}
if (!(TimeoutRemaining))
return TWI_ERROR_SlaveResponseTimeout;
switch (TWSR & TW_STATUS_MASK)
{
case TW_MT_SLA_ACK:
case TW_MR_SLA_ACK:
return TWI_ERROR_NoError;
default:
TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN));
return TWI_ERROR_SlaveNotReady;
}
}
}
bool TWI_SendByte(const uint8_t Byte)
{
TWDR = Byte;
TWCR = ((1 << TWINT) | (1 << TWEN));
while (!(TWCR & (1 << TWINT)));
return ((TWSR & TW_STATUS_MASK) == TW_MT_DATA_ACK);
}
bool TWI_ReceiveByte(uint8_t* const Byte,
const bool LastByte)
{
uint8_t TWCRMask;
if (LastByte)
TWCRMask = ((1 << TWINT) | (1 << TWEN));
else
TWCRMask = ((1 << TWINT) | (1 << TWEN) | (1 << TWEA));
TWCR = TWCRMask;
while (!(TWCR & (1 << TWINT)));
*Byte = TWDR;
uint8_t Status = (TWSR & TW_STATUS_MASK);
return ((LastByte) ? (Status == TW_MR_DATA_NACK) : (Status == TW_MR_DATA_ACK));
}
uint8_t TWI_ReadPacket(const uint8_t SlaveAddress,
const uint8_t TimeoutMS,
const uint8_t* InternalAddress,
uint8_t InternalAddressLen,
uint8_t* Buffer,
uint8_t Length)
{
uint8_t ErrorCode;
if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
TimeoutMS)) == TWI_ERROR_NoError)
{
while (InternalAddressLen--)
{
if (!(TWI_SendByte(*(InternalAddress++))))
{
ErrorCode = TWI_ERROR_SlaveNAK;
break;
}
}
if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_READ,
TimeoutMS)) == TWI_ERROR_NoError)
{
while (Length--)
{
if (!(TWI_ReceiveByte(Buffer++, (Length == 0))))
{
ErrorCode = TWI_ERROR_SlaveNAK;
break;
}
}
TWI_StopTransmission();
}
}
return ErrorCode;
}
uint8_t TWI_WritePacket(const uint8_t SlaveAddress,
const uint8_t TimeoutMS,
const uint8_t* InternalAddress,
uint8_t InternalAddressLen,
const uint8_t* Buffer,
uint8_t Length)
{
uint8_t ErrorCode;
if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
TimeoutMS)) == TWI_ERROR_NoError)
{
while (InternalAddressLen--)
{
if (!(TWI_SendByte(*(InternalAddress++))))
{
ErrorCode = TWI_ERROR_SlaveNAK;
break;
}
}
while (Length--)
{
if (!(TWI_SendByte(*(Buffer++))))
{
ErrorCode = TWI_ERROR_SlaveNAK;
break;
}
}
TWI_StopTransmission();
}
return ErrorCode;
}
#endif

View file

@ -0,0 +1,305 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 TWI Peripheral Driver (AVR8)
*
* On-chip TWI driver for the 8-bit AVR microcontrollers.
*
* \note This file should not be included directly. It is automatically included as needed by the TWI driver
* dispatch header located in LUFA/Drivers/Peripheral/TWI.h.
*/
/** \ingroup Group_TWI
* \defgroup Group_TWI_AVR8 TWI Peripheral Driver (AVR8)
*
* \section Sec_TWI_AVR8_ModDescription Module Description
* Master mode TWI driver for the 8-bit AVR microcontrollers which contain a hardware TWI module.
*
* \note This file should not be included directly. It is automatically included as needed by the TWI driver
* dispatch header located in LUFA/Drivers/Peripheral/TWI.h.
*
* \section Sec_TWI_AVR8_ExampleUsage Example Usage
* The following snippet is an example of how this module may be used within a typical
* application.
*
* <b>Low Level API Example:</b>
* \code
* // Initialize the TWI driver before first use at 200KHz
* TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 200000));
*
* // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout
* if (TWI_StartTransmission(0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError)
* {
* TWI_SendByte(0xDC);
*
* TWI_SendByte(0x01);
* TWI_SendByte(0x02);
* TWI_SendByte(0x03);
*
* // Must stop transmission afterwards to release the bus
* TWI_StopTransmission();
* }
*
* // Start a read session to device at address 0xA0, internal address 0xDC with a 10ms timeout
* if (TWI_StartTransmission(0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError)
* {
* TWI_SendByte(0xDC);
* TWI_StopTransmission();
*
* if (TWI_StartTransmission(0xA0 | TWI_ADDRESS_READ, 10) == TWI_ERROR_NoError)
* {
* uint8_t Byte1, Byte2, Byte3;
*
* // Read three bytes, acknowledge after the third byte is received
* TWI_ReceiveByte(&Byte1, false);
* TWI_ReceiveByte(&Byte2, false);
* TWI_ReceiveByte(&Byte3, true);
*
* // Must stop transmission afterwards to release the bus
* TWI_StopTransmission();
* }
* }
* \endcode
*
* <b>High Level API Example:</b>
* \code
* // Initialize the TWI driver before first use at 200KHz
* TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 200000));
*
* // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout
* uint8_t InternalWriteAddress = 0xDC;
* uint8_t WritePacket[3] = {0x01, 0x02, 0x03};
*
* TWI_WritePacket(0xA0, 10, &InternalWriteAddress, sizeof(InternalWriteAddress),
* &WritePacket, sizeof(WritePacket);
*
* // Start a read session to device at address 0xA0, internal address 0xDC with a 10ms timeout
* uint8_t InternalReadAddress = 0xDC;
* uint8_t ReadPacket[3];
*
* TWI_ReadPacket(0xA0, 10, &InternalReadAddress, sizeof(InternalReadAddress),
* &ReadPacket, sizeof(ReadPacket);
* \endcode
*
* @{
*/
#ifndef __TWI_AVR8_H__
#define __TWI_AVR8_H__
/* Includes: */
#include "../../../Common/Common.h"
#include <stdio.h>
#include <util/twi.h>
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_TWI_H) && !defined(__INCLUDE_FROM_TWI_C)
#error Do not include this file directly. Include LUFA/Drivers/Peripheral/TWI.h instead.
#endif
#if !(defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \
defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
#error The TWI peripheral driver is not currently available for your selected microcontroller model.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** TWI slave device address mask for a read session. Mask with a slave device base address to obtain
* the correct TWI bus address for the slave device when reading data from it.
*/
#define TWI_ADDRESS_READ 0x01
/** TWI slave device address mask for a write session. Mask with a slave device base address to obtain
* the correct TWI bus address for the slave device when writing data to it.
*/
#define TWI_ADDRESS_WRITE 0x00
/** Mask to retrieve the base address for a TWI device, which can then be ORed with \ref TWI_ADDRESS_READ
* or \ref TWI_ADDRESS_WRITE to obtain the device's read and write address respectively.
*/
#define TWI_DEVICE_ADDRESS_MASK 0xFE
/** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 1. */
#define TWI_BIT_PRESCALE_1 ((0 << TWPS1) | (0 << TWPS0))
/** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 4. */
#define TWI_BIT_PRESCALE_4 ((0 << TWPS1) | (1 << TWPS0))
/** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 16. */
#define TWI_BIT_PRESCALE_16 ((1 << TWPS1) | (0 << TWPS0))
/** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 64. */
#define TWI_BIT_PRESCALE_64 ((1 << TWPS1) | (1 << TWPS0))
/** Calculates the length of each bit on the TWI bus for a given target frequency. This may be used with
* the \ref TWI_Init() function to convert a bus frequency to a number of clocks for the \c BitLength
* parameter.
*
* \param[in] Prescale Prescaler set on the TWI bus.
* \param[in] Frequency Desired TWI bus frequency in Hz.
*
* \return Bit length in clocks for the given TWI bus frequency at the given prescaler value.
*/
#define TWI_BITLENGTH_FROM_FREQ(Prescale, Frequency) ((((F_CPU / (Prescale)) / (Frequency)) - 16) / 2)
/* Enums: */
/** Enum for the possible return codes of the TWI transfer start routine and other dependant TWI functions. */
enum TWI_ErrorCodes_t
{
TWI_ERROR_NoError = 0, /**< Indicates that the command completed successfully. */
TWI_ERROR_BusFault = 1, /**< A TWI bus fault occurred while attempting to capture the bus. */
TWI_ERROR_BusCaptureTimeout = 2, /**< A timeout occurred whilst waiting for the bus to be ready. */
TWI_ERROR_SlaveResponseTimeout = 3, /**< No ACK received at the nominated slave address within the timeout period. */
TWI_ERROR_SlaveNotReady = 4, /**< Slave NAKed the TWI bus START condition. */
TWI_ERROR_SlaveNAK = 5, /**< Slave NAKed whilst attempting to send data to the device. */
};
/* Inline Functions: */
/** Initializes the TWI hardware into master mode, ready for data transmission and reception. This must be
* before any other TWI operations.
*
* The generated SCL frequency will be according to the formula <pre>F_CPU / (16 + 2 * BitLength + 4 ^ Prescale)</pre>.
*
* \attention The value of the \c BitLength parameter should not be set below 10 or invalid bus conditions may
* occur, as indicated in the AVR8 microcontroller datasheet.
*
* \param[in] Prescale Prescaler to use when determining the bus frequency, a \c TWI_BIT_PRESCALE_* value.
* \param[in] BitLength Length of the bits sent on the bus.
*/
static inline void TWI_Init(const uint8_t Prescale,
const uint8_t BitLength) ATTR_ALWAYS_INLINE;
static inline void TWI_Init(const uint8_t Prescale,
const uint8_t BitLength)
{
TWCR |= (1 << TWEN);
TWSR = Prescale;
TWBR = BitLength;
}
/** 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_Disable(void) ATTR_ALWAYS_INLINE;
static inline void TWI_Disable(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));
}
/* Function Prototypes: */
/** Begins a master mode TWI bus communication with the given slave device address.
*
* \param[in] SlaveAddress Address of the slave TWI device to communicate with.
* \param[in] TimeoutMS Timeout period within which the slave must respond, in milliseconds.
*
* \return A value from the \ref TWI_ErrorCodes_t enum.
*/
uint8_t TWI_StartTransmission(const uint8_t SlaveAddress,
const uint8_t TimeoutMS);
/** Sends a byte to the currently addressed device on the TWI bus.
*
* \param[in] Byte Byte to send to the currently addressed device
*
* \return Boolean \c true if the recipient ACKed the byte, \c false otherwise
*/
bool TWI_SendByte(const uint8_t Byte);
/** Receives a byte from the currently addressed device on the TWI bus.
*
* \param[in] Byte Location where the read byte is to be stored.
* \param[in] LastByte Indicates if the byte should be ACKed if false, NAKed if true.
*
* \return Boolean \c true if the byte reception successfully completed, \c false otherwise.
*/
bool TWI_ReceiveByte(uint8_t* const Byte,
const bool LastByte) ATTR_NON_NULL_PTR_ARG(1);
/** High level function to perform a complete packet transfer over the TWI bus to the specified
* device.
*
* \param[in] SlaveAddress Base address of the TWI slave device to communicate with.
* \param[in] TimeoutMS Timeout for bus capture and slave START ACK, in milliseconds.
* \param[in] InternalAddress Pointer to a location where the internal slave read start address is stored.
* \param[in] InternalAddressLen Size of the internal device address, in bytes.
* \param[in] Buffer Pointer to a buffer where the read packet data is to be stored.
* \param[in] Length Size of the packet to read, in bytes.
*
* \return A value from the \ref TWI_ErrorCodes_t enum.
*/
uint8_t TWI_ReadPacket(const uint8_t SlaveAddress,
const uint8_t TimeoutMS,
const uint8_t* InternalAddress,
uint8_t InternalAddressLen,
uint8_t* Buffer,
uint8_t Length) ATTR_NON_NULL_PTR_ARG(3);
/** High level function to perform a complete packet transfer over the TWI bus from the specified
* device.
*
* \param[in] SlaveAddress Base address of the TWI slave device to communicate with
* \param[in] TimeoutMS Timeout for bus capture and slave START ACK, in milliseconds
* \param[in] InternalAddress Pointer to a location where the internal slave write start address is stored
* \param[in] InternalAddressLen Size of the internal device address, in bytes
* \param[in] Buffer Pointer to a buffer where the packet data to send is stored
* \param[in] Length Size of the packet to send, in bytes
*
* \return A value from the \ref TWI_ErrorCodes_t enum.
*/
uint8_t TWI_WritePacket(const uint8_t SlaveAddress,
const uint8_t TimeoutMS,
const uint8_t* InternalAddress,
uint8_t InternalAddressLen,
const uint8_t* Buffer,
uint8_t Length) ATTR_NON_NULL_PTR_ARG(3);
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,76 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Serial Peripheral Interface driver.
*
* This file is the master dispatch header file for the device-specific SPI driver, for microcontrollers
* containing a hardware SPI.
*
* User code should include this file, which will in turn include the correct SPI driver header file for the
* currently selected architecture and microcontroller model.
*/
/** \ingroup Group_PeripheralDrivers
* \defgroup Group_SPI SPI Driver - LUFA/Drivers/Peripheral/SPI.h
* \brief Hardware Serial Peripheral Interface driver.
*
* \section Sec_SPI_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - None
*
* \section Sec_SPI_ModDescription Module Description
* Hardware SPI driver. This module provides an easy to use driver for the setup and transfer of data over
* the selected architecture and microcontroller model's SPI port.
*
* \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 __SPI_H__
#define __SPI_H__
/* Macros: */
#define __INCLUDE_FROM_SPI_H
/* Includes: */
#include "../../Common/Common.h"
/* Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/SPI_AVR8.h"
#elif (ARCH == ARCH_XMEGA)
#include "XMEGA/SPI_XMEGA.h"
#else
#error The SPI peripheral driver is not currently available for your selected architecture.
#endif
#endif

View file

@ -0,0 +1,76 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Serial USART driver.
*
* This file is the master dispatch header file for the device-specific USART driver, for microcontrollers
* containing a hardware USART.
*
* 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_Serial Serial USART Driver - LUFA/Drivers/Peripheral/Serial.h
* \brief Hardware Serial USART driver.
*
* \section Sec_Serial_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/Peripheral/<i>ARCH</i>/Serial_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_SERIAL)</i>
*
* \section Sec_Serial_ModDescription Module Description
* Hardware 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.
*
* \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_H__
#define __SERIAL_H__
/* Macros: */
#define __INCLUDE_FROM_SERIAL_H
/* Includes: */
#include "../../Common/Common.h"
/* Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/Serial_AVR8.h"
#elif (ARCH == ARCH_XMEGA)
#include "XMEGA/Serial_XMEGA.h"
#else
#error The Serial peripheral driver is not currently available for your selected architecture.
#endif
#endif

View file

@ -0,0 +1,76 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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_SerialSPI_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - None
*
* \section Sec_SerialSPI_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

View file

@ -0,0 +1,76 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Two Wire Interface (I2C) driver.
*
* This file is the master dispatch header file for the device-specific SPI driver, for microcontrollers
* containing a hardware TWI.
*
* User code should include this file, which will in turn include the correct TWI driver header file for the
* currently selected architecture and microcontroller model.
*/
/** \ingroup Group_PeripheralDrivers
* \defgroup Group_TWI TWI Driver - LUFA/Drivers/Peripheral/TWI.h
* \brief Hardware Two Wire Interface (I2C) driver.
*
* \section Sec_TWI_Dependencies Module Source Dependencies
* The following files must be built with any user project that uses this module:
* - LUFA/Drivers/Peripheral/<i>ARCH</i>/TWI_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_TWI)</i>
*
* \section Sec_TWI_ModDescription Module Description
* Hardware TWI driver. This module provides an easy to use driver for the setup and transfer of data over
* the selected architecture and microcontroller model's TWI bus port.
*
* \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 __TWI_H__
#define __TWI_H__
/* Macros: */
#define __INCLUDE_FROM_TWI_H
/* Includes: */
#include "../../Common/Common.h"
/* Includes: */
#if (ARCH == ARCH_AVR8)
#include "AVR8/TWI_AVR8.h"
#elif (ARCH == ARCH_XMEGA)
#include "XMEGA/TWI_XMEGA.h"
#else
#error The TWI peripheral driver is not currently available for your selected architecture.
#endif
#endif

View file

@ -0,0 +1,251 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 SPI Peripheral Driver (XMEGA)
*
* On-chip SPI driver for the XMEGA microcontrollers.
*
* \note This file should not be included directly. It is automatically included as needed by the SPI driver
* dispatch header located in LUFA/Drivers/Peripheral/SPI.h.
*/
/** \ingroup Group_SPI
* \defgroup Group_SPI_XMEGA SPI Peripheral Driver (XMEGA)
*
* \section Sec_SPI_XMEGA_ModDescription Module Description
* Driver for the hardware SPI port(s) available on XMEGA AVR microcontroller models. This
* module provides an easy to use driver for the setup and transfer of data over the AVR's
* SPI ports.
*
* \note This file should not be included directly. It is automatically included as needed by the SPI driver
* dispatch header located in LUFA/Drivers/Peripheral/SPI.h.
*
* \code
* // Initialize the SPI driver before first use
* SPI_Init(&SPIC,
* SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING |
* SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
*
* // Send several bytes, ignoring the returned data
* SPI_SendByte(&SPIC, 0x01);
* SPI_SendByte(&SPIC, 0x02);
* SPI_SendByte(&SPIC, 0x03);
*
* // Receive several bytes, sending a dummy 0x00 byte each time
* uint8_t Byte1 = SPI_ReceiveByte(&SPIC);
* uint8_t Byte2 = SPI_ReceiveByte(&SPIC);
* uint8_t Byte3 = SPI_ReceiveByte(&SPIC);
*
* // Send a byte, and store the received byte from the same transaction
* uint8_t ResponseByte = SPI_TransferByte(&SPIC, 0xDC);
* \endcode
*
* @{
*/
#ifndef __SPI_XMEGA_H__
#define __SPI_XMEGA_H__
/* Includes: */
#include "../../../Common/Common.h"
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_SPI_H)
#error Do not include this file directly. Include LUFA/Drivers/Peripheral/SPI.h instead.
#endif
/* Private Interface - For use in library only: */
#if !defined(__DOXYGEN__)
/* Macros: */
#define SPI_USE_DOUBLESPEED SPI_CLK2X_bm
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** \name SPI Prescaler Configuration Masks */
//@{
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 2. */
#define SPI_SPEED_FCPU_DIV_2 SPI_USE_DOUBLESPEED
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 4. */
#define SPI_SPEED_FCPU_DIV_4 0
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 8. */
#define SPI_SPEED_FCPU_DIV_8 (SPI_USE_DOUBLESPEED | (1 << SPI_PRESCALER_gp))
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 16. */
#define SPI_SPEED_FCPU_DIV_16 (1 << SPI_PRESCALER_gp)
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 32. */
#define SPI_SPEED_FCPU_DIV_32 (SPI_USE_DOUBLESPEED | (2 << SPI_PRESCALER_gp))
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 64. */
#define SPI_SPEED_FCPU_DIV_64 (2 << SPI_PRESCALER_gp)
/** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 128. */
#define SPI_SPEED_FCPU_DIV_128 (3 << SPI_PRESCALER_gp)
//@}
/** \name SPI SCK Polarity Configuration Masks */
//@{
/** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the rising edge. */
#define SPI_SCK_LEAD_RISING 0
/** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the falling edge. */
#define SPI_SCK_LEAD_FALLING SPI_MODE1_bm
//@}
/** \name SPI Sample Edge Configuration Masks */
//@{
/** SPI data sample mode mask for \ref SPI_Init(). Indicates that the data should sampled on the leading edge. */
#define SPI_SAMPLE_LEADING 0
/** SPI data sample mode mask for \ref SPI_Init(). Indicates that the data should be sampled on the trailing edge. */
#define SPI_SAMPLE_TRAILING SPI_MODE0_bm
//@}
/** \name SPI Data Ordering Configuration Masks */
//@{
/** SPI data order mask for \ref SPI_Init(). Indicates that data should be shifted out MSB first. */
#define SPI_ORDER_MSB_FIRST 0
/** SPI data order mask for \ref SPI_Init(). Indicates that data should be shifted out LSB first. */
#define SPI_ORDER_LSB_FIRST SPI_DORD_bm
//@}
/** \name SPI Mode Configuration Masks */
//@{
/** SPI mode mask for \ref SPI_Init(). Indicates that the SPI interface should be initialized into slave mode. */
#define SPI_MODE_SLAVE 0
/** SPI mode mask for \ref SPI_Init(). Indicates that the SPI interface should be initialized into master mode. */
#define SPI_MODE_MASTER SPI_MASTER_bm
//@}
/* Inline Functions: */
/** Initializes the SPI subsystem, ready for transfers. Must be called before calling any other
* SPI routines.
*
* \param[in,out] SPI Pointer to the base of the SPI peripheral within the device.
* \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(SPI_t* const SPI,
const uint8_t SPIOptions) ATTR_NON_NULL_PTR_ARG(1);
static inline void SPI_Init(SPI_t* const SPI,
const uint8_t SPIOptions)
{
SPI->CTRL = (SPIOptions | SPI_ENABLE_bm);
}
/** 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.
*/
static inline void SPI_Disable(SPI_t* const SPI) ATTR_NON_NULL_PTR_ARG(1);
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.
*
* \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(SPI_t* const SPI) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline uint8_t SPI_GetCurrentMode(SPI_t* const SPI)
{
return (SPI->CTRL & SPI_MASTER_bm);
}
/** Sends and receives a byte through the SPI interface, blocking until the transfer is complete.
*
* \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.
*
* \return Response byte from the attached SPI device.
*/
static inline uint8_t SPI_TransferByte(SPI_t* const SPI,
const uint8_t Byte) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline uint8_t SPI_TransferByte(SPI_t* const SPI,
const uint8_t Byte)
{
SPI->DATA = Byte;
while (!(SPI->STATUS & SPI_IF_bm));
return SPI->DATA;
}
/** Sends a byte through the SPI interface, blocking until the transfer is complete. The response
* byte sent to from the attached SPI device is ignored.
*
* \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(SPI_t* const SPI,
const uint8_t Byte) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline void SPI_SendByte(SPI_t* const SPI,
const uint8_t Byte)
{
SPI->DATA = Byte;
while (!(SPI->STATUS & SPI_IF_bm));
}
/** Sends a dummy byte through the SPI interface, blocking until the transfer is complete. The response
* byte from the attached SPI device is returned.
*
* \param[in,out] SPI Pointer to the base of the SPI peripheral within the device.
*
* \return The response byte from the attached SPI device.
*/
static inline uint8_t SPI_ReceiveByte(SPI_t* const SPI) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static inline uint8_t SPI_ReceiveByte(SPI_t* const SPI)
{
SPI->DATA = 0;
while (!(SPI->STATUS & SPI_IF_bm));
return SPI->DATA;
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,212 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 Master SPI Mode Serial USART 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 Master SPI Mode Serial USART Peripheral Driver (XMEGA)
*
* \section Sec_SerialSPI_XMEGA_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_SerialSPI_XMEGA_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(&USARTD0, (USART_SPI_SCK_LEAD_RISING | USART_SPI_SAMPLE_LEADING | USART_SPI_ORDER_MSB_FIRST), 1000000);
*
* // Send several bytes, ignoring the returned data
* SerialSPI_SendByte(&USARTD0, 0x01);
* SerialSPI_SendByte(&USARTD0, 0x02);
* SerialSPI_SendByte(&USARTD0, 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(&USARTD0, 0xDC);
* \endcode
*
* @{
*/
#ifndef __SERIAL_SPI_XMEGA_H__
#define __SERIAL_SPI_XMEGA_H__
/* Includes: */
#include "../../../Common/Common.h"
#include <stdio.h>
/* 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 \ref 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 \ref SerialSPI_Init(). Indicates that the data should sampled on the leading edge. */
#define USART_SPI_SAMPLE_LEADING 0
/** SPI data sample mode mask for \ref SerialSPI_Init(). Indicates that the data should be sampled on the trailing edge. */
#define USART_SPI_SAMPLE_TRAILING (1 << 1)
//@}
/** \name SPI Data Ordering Configuration Masks */
//@{
/** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out MSB first. */
#define USART_SPI_ORDER_MSB_FIRST 0
/** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out LSB first. */
#define USART_SPI_ORDER_LSB_FIRST (1 << 2)
//@}
/* 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) ATTR_NON_NULL_PTR_ARG(1);
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) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
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) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
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) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline void SerialSPI_SendByte(USART_t* const USART,
const uint8_t DataByte)
{
SerialSPI_TransferByte(USART, DataByte);
}
/** 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) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static inline uint8_t SerialSPI_ReceiveByte(USART_t* const USART)
{
return SerialSPI_TransferByte(USART, 0);
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,122 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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.
*/
#include "../../../Common/Common.h"
#if (ARCH == ARCH_XMEGA)
#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 void* Buffer,
uint16_t Length)
{
while (Length--)
Serial_SendByte(USART, *((uint8_t*)Buffer++));
}
void Serial_CreateStream(FILE* Stream)
{
if (!(Stream))
{
Stream = &USARTSerialStream;
stdin = Stream;
stdout = Stream;
}
*Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar, _FDEV_SETUP_RW);
}
void Serial_CreateBlockingStream(FILE* Stream)
{
if (!(Stream))
{
Stream = &USARTSerialStream;
stdin = Stream;
stdout = Stream;
}
*Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar_Blocking, _FDEV_SETUP_RW);
}
#endif

View file

@ -0,0 +1,286 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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_Serial_XMEGA_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 USART driver
* dispatch header located in LUFA/Drivers/Peripheral/Serial.h.
*
* \section Sec_Serial_XMEGA_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(&USARTD0, 9600, false);
*
* // Send a string through the USART
* Serial_TxString(&USARTD0, "Test String\r\n");
*
* // Receive a byte through the USART
* uint8_t DataByte = Serial_RxByte(&USARTD0);
* \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 void* Buffer,
uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
/** 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] 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.
*/
void Serial_CreateStream(FILE* Stream);
/** Identical to \ref Serial_CreateStream(), except that reads are blocking until the calling stream function terminates
* the transfer.
*
* \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL, \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.
*/
void Serial_CreateBlockingStream(FILE* Stream);
/* 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) ATTR_NON_NULL_PTR_ARG(1);
static inline void Serial_Init(USART_t* const USART,
const uint32_t BaudRate,
const bool DoubleSpeed)
{
uint16_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) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline void Serial_Disable(USART_t* const USART)
{
USART->CTRLA = 0;
USART->CTRLB = 0;
USART->CTRLC = 0;
}
/** 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_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static inline bool Serial_IsCharReceived(USART_t* const USART)
{
return ((USART->STATUS & USART_RXCIF_bm) ? true : false);
}
/** Indicates whether there is hardware buffer space for a new transmit on the USART. This
* function can be used to determine if a call to \ref Serial_SendByte() will block in advance.
*
* \param[in,out] USART Pointer to the base of the USART peripheral within the device.
*
* \return Boolean \c true if a character can be queued for transmission immediately, \c false otherwise.
*/
static inline bool Serial_IsSendReady(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static inline bool Serial_IsSendReady(USART_t* const USART)
{
return (USART->STATUS & USART_DREIF_bm) ? true : false;
}
/** Indicates whether the hardware USART transmit buffer is completely empty, indicating all
* pending transmissions have completed.
*
* \param[in,out] USART Pointer to the base of the USART peripheral within the device.
*
* \return Boolean \c true if no characters are buffered for transmission, \c false otherwise.
*/
static inline bool Serial_IsSendComplete(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
static inline bool Serial_IsSendComplete(USART_t* const USART)
{
return (USART->STATUS & USART_TXCIF_bm) ? true : false;
}
/** Transmits a given byte through the USART.
*
* \note If no buffer space is available in the hardware USART, this function will block. To check if
* space is available before calling this function, see \ref Serial_IsSendReady().
*
* \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 ATTR_NON_NULL_PTR_ARG(1);
static inline void Serial_SendByte(USART_t* const USART,
const char DataByte)
{
while (!(Serial_IsSendReady(USART)));
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 ATTR_NON_NULL_PTR_ARG(1);
static inline int16_t Serial_ReceiveByte(USART_t* const USART)
{
if (!(Serial_IsCharReceived(USART)))
return -1;
USART->STATUS = USART_RXCIF_bm;
return USART->DATA;
}
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */

View file

@ -0,0 +1,185 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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.
*/
#include "../../../Common/Common.h"
#if (ARCH == ARCH_XMEGA)
#define __INCLUDE_FROM_TWI_C
#include "../TWI.h"
uint8_t TWI_StartTransmission(TWI_t* const TWI,
const uint8_t SlaveAddress,
const uint8_t TimeoutMS)
{
uint16_t TimeoutRemaining;
TWI->MASTER.ADDR = SlaveAddress;
TimeoutRemaining = (TimeoutMS * 100);
while (TimeoutRemaining)
{
uint8_t status = TWI->MASTER.STATUS;
if ((status & (TWI_MASTER_WIF_bm | TWI_MASTER_ARBLOST_bm)) == (TWI_MASTER_WIF_bm | TWI_MASTER_ARBLOST_bm))
{
TWI->MASTER.ADDR = SlaveAddress;
}
else if ((status & (TWI_MASTER_WIF_bm | TWI_MASTER_RXACK_bm)) == (TWI_MASTER_WIF_bm | TWI_MASTER_RXACK_bm))
{
TWI_StopTransmission(TWI);
return TWI_ERROR_SlaveResponseTimeout;
}
else if (status & (TWI_MASTER_WIF_bm | TWI_MASTER_RIF_bm))
{
return TWI_ERROR_NoError;
}
_delay_us(10);
TimeoutRemaining--;
}
if (!(TimeoutRemaining)) {
if (TWI->MASTER.STATUS & TWI_MASTER_CLKHOLD_bm) {
TWI_StopTransmission(TWI);
}
}
return TWI_ERROR_BusCaptureTimeout;
}
bool TWI_SendByte(TWI_t* const TWI,
const uint8_t Byte)
{
TWI->MASTER.DATA = Byte;
while (!(TWI->MASTER.STATUS & TWI_MASTER_WIF_bm));
return (TWI->MASTER.STATUS & TWI_MASTER_WIF_bm) && !(TWI->MASTER.STATUS & TWI_MASTER_RXACK_bm);
}
bool TWI_ReceiveByte(TWI_t* const TWI,
uint8_t* const Byte,
const bool LastByte)
{
if ((TWI->MASTER.STATUS & (TWI_MASTER_BUSERR_bm | TWI_MASTER_ARBLOST_bm)) == (TWI_MASTER_BUSERR_bm | TWI_MASTER_ARBLOST_bm)) {
return false;
}
while (!(TWI->MASTER.STATUS & TWI_MASTER_RIF_bm));
*Byte = TWI->MASTER.DATA;
if (LastByte)
TWI->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc;
else
TWI->MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
return true;
}
uint8_t TWI_ReadPacket(TWI_t* const TWI,
const uint8_t SlaveAddress,
const uint8_t TimeoutMS,
const uint8_t* InternalAddress,
uint8_t InternalAddressLen,
uint8_t* Buffer,
uint8_t Length)
{
uint8_t ErrorCode;
if ((ErrorCode = TWI_StartTransmission(TWI, (SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
TimeoutMS)) == TWI_ERROR_NoError)
{
while (InternalAddressLen--)
{
if (!(TWI_SendByte(TWI, *(InternalAddress++))))
{
ErrorCode = TWI_ERROR_SlaveNAK;
break;
}
}
if ((ErrorCode = TWI_StartTransmission(TWI, (SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_READ,
TimeoutMS)) == TWI_ERROR_NoError)
{
while (Length--)
{
if (!(TWI_ReceiveByte(TWI, Buffer++, (Length == 0))))
{
ErrorCode = TWI_ERROR_SlaveNAK;
break;
}
}
}
TWI_StopTransmission(TWI);
}
return ErrorCode;
}
uint8_t TWI_WritePacket(TWI_t* const TWI,
const uint8_t SlaveAddress,
const uint8_t TimeoutMS,
const uint8_t* InternalAddress,
uint8_t InternalAddressLen,
const uint8_t* Buffer,
uint8_t Length)
{
uint8_t ErrorCode;
if ((ErrorCode = TWI_StartTransmission(TWI, (SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
TimeoutMS)) == TWI_ERROR_NoError)
{
while (InternalAddressLen--)
{
if (!(TWI_SendByte(TWI, *(InternalAddress++))))
{
ErrorCode = TWI_ERROR_SlaveNAK;
break;
}
}
while (Length--)
{
if (!(TWI_SendByte(TWI, *(Buffer++))))
{
ErrorCode = TWI_ERROR_SlaveNAK;
break;
}
}
TWI_StopTransmission(TWI);
}
return ErrorCode;
}
#endif

View file

@ -0,0 +1,302 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 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 disclaims 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 TWI Peripheral Driver (XMEGA)
*
* On-chip TWI driver for the XMEGA Family of AVR microcontrollers.
*
* \note This file should not be included directly. It is automatically included as needed by the TWI driver
* dispatch header located in LUFA/Drivers/Peripheral/TWI.h.
*/
/** \ingroup Group_TWI
* \defgroup Group_TWI_XMEGA TWI Peripheral Driver (XMEGA)
*
* \section Sec_TWI_XMEGA_ModDescription Module Description
* Master mode TWI driver for the 8-bit AVR microcontrollers which contain a hardware TWI module.
*
* \note This file should not be included directly. It is automatically included as needed by the TWI driver
* dispatch header located in LUFA/Drivers/Peripheral/TWI.h.
*
* \section Sec_TWI_XMEGA_ExampleUsage Example Usage
* The following snippet is an example of how this module may be used within a typical
* application.
*
* <b>Low Level API Example:</b>
* \code
* // Initialize the TWI driver before first use at 200KHz
* TWI_Init(&TWIC, TWI_BAUD_FROM_FREQ(200000));
*
* // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout
* if (TWI_StartTransmission(&TWIC, 0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError)
* {
* TWI_SendByte(&TWIC, 0xDC);
*
* TWI_SendByte(&TWIC, 0x01);
* TWI_SendByte(&TWIC, 0x02);
* TWI_SendByte(&TWIC, 0x03);
*
* // Must stop transmission afterwards to release the bus
* TWI_StopTransmission(&TWIC);
* }
*
* // Start a read session to device at address 0xA0, internal address 0xDC with a 10ms timeout
* if (TWI_StartTransmission(&TWIC, 0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError)
* {
* TWI_SendByte(&TWIC, 0xDC);
* TWI_StopTransmission(&TWIC);
*
* if (TWI_StartTransmission(&TWIC, 0xA0 | TWI_ADDRESS_READ, 10) == TWI_ERROR_NoError)
* {
* uint8_t Byte1, Byte2, Byte3;
*
* // Read three bytes, acknowledge after the third byte is received
* TWI_ReceiveByte(&TWIC, &Byte1, false);
* TWI_ReceiveByte(&TWIC, &Byte2, false);
* TWI_ReceiveByte(&TWIC, &Byte3, true);
*
* // Must stop transmission afterwards to release the bus
* TWI_StopTransmission(&TWIC);
* }
* }
* \endcode
*
* <b>High Level API Example:</b>
* \code
* // Initialize the TWI driver before first use at 200KHz
* TWI_Init(&TWIC, TWI_BAUD_FROM_FREQ(200000));
*
* // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout
* uint8_t InternalWriteAddress = 0xDC;
* uint8_t WritePacket[3] = {0x01, 0x02, 0x03};
*
* TWI_WritePacket(&TWIC, 0xA0, 10, &InternalWriteAddress, sizeof(InternalWriteAddress),
* &WritePacket, sizeof(WritePacket);
*
* // Start a read session to device at address 0xA0, internal address 0xDC with a 10ms timeout
* uint8_t InternalReadAddress = 0xDC;
* uint8_t ReadPacket[3];
*
* TWI_ReadPacket(&TWIC, 0xA0, 10, &InternalReadAddress, sizeof(InternalReadAddress),
* &ReadPacket, sizeof(ReadPacket);
* \endcode
*
* @{
*/
#ifndef __TWI_XMEGA_H__
#define __TWI_XMEGA_H__
/* Includes: */
#include "../../../Common/Common.h"
#include <stdio.h>
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C" {
#endif
/* Preprocessor Checks: */
#if !defined(__INCLUDE_FROM_TWI_H) && !defined(__INCLUDE_FROM_TWI_C)
#error Do not include this file directly. Include LUFA/Drivers/Peripheral/TWI.h instead.
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** TWI slave device address mask for a read session. Mask with a slave device base address to obtain
* the correct TWI bus address for the slave device when reading data from it.
*/
#define TWI_ADDRESS_READ 0x01
/** TWI slave device address mask for a write session. Mask with a slave device base address to obtain
* the correct TWI bus address for the slave device when writing data to it.
*/
#define TWI_ADDRESS_WRITE 0x00
/** Mask to retrieve the base address for a TWI device, which can then be ORed with \ref TWI_ADDRESS_READ
* or \ref TWI_ADDRESS_WRITE to obtain the device's read and write address respectively.
*/
#define TWI_DEVICE_ADDRESS_MASK 0xFE
/** Calculates the length of each bit on the TWI bus for a given target frequency. This may be used with
* the \ref TWI_Init() function to convert a bus frequency to a number of clocks for the \c BitLength
* parameter.
*
* \param[in] Frequency Desired TWI bus frequency in Hz.
*
* \return Bit length in clocks for the given TWI bus frequency at the given prescaler value.
*/
#define TWI_BAUD_FROM_FREQ(Frequency) ((F_CPU / (2 * Frequency)) - 5)
/* Enums: */
/** Enum for the possible return codes of the TWI transfer start routine and other dependant TWI functions. */
enum TWI_ErrorCodes_t
{
TWI_ERROR_NoError = 0, /**< Indicates that the command completed successfully. */
TWI_ERROR_BusFault = 1, /**< A TWI bus fault occurred while attempting to capture the bus. */
TWI_ERROR_BusCaptureTimeout = 2, /**< A timeout occurred whilst waiting for the bus to be ready. */
TWI_ERROR_SlaveResponseTimeout = 3, /**< No ACK received at the nominated slave address within the timeout period. */
TWI_ERROR_SlaveNotReady = 4, /**< Slave NAKed the TWI bus START condition. */
TWI_ERROR_SlaveNAK = 5, /**< Slave NAKed whilst attempting to send data to the device. */
};
/* Inline Functions: */
/** Initializes the TWI hardware into master mode, ready for data transmission and reception. This must be
* before any other TWI operations.
*
* The generated SCL frequency will be according to the formula <pre>F_CPU / (2 * (5 + (BAUD)))</pre>.
*
* \attention The value of the \c BitLength parameter should not be set below 10 or invalid bus conditions may
* occur, as indicated in the XMEGA microcontroller datasheet.
*
* \param[in] TWI Pointer to the base of the TWI peripheral within the device.
* \param[in] Baud Value of the BAUD register of the TWI Master.
*/
static inline void TWI_Init(TWI_t* const TWI,
const uint8_t Baud) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline void TWI_Init(TWI_t* const TWI,
const uint8_t Baud)
{
TWI->CTRL = 0x00;
TWI->MASTER.BAUD = Baud;
TWI->MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
TWI->MASTER.CTRLB = 0;
TWI->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
}
/** 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.
*
* \param[in] TWI Pointer to the base of the TWI peripheral within the device.
*/
static inline void TWI_Disable(TWI_t* const TWI) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline void TWI_Disable(TWI_t* const TWI)
{
TWI->MASTER.CTRLA &= ~TWI_MASTER_ENABLE_bm;
}
/** Sends a TWI STOP onto the TWI bus, terminating communication with the currently addressed device.
*
* \param[in] TWI Pointer to the base of the TWI peripheral within the device.
*/
static inline void TWI_StopTransmission(TWI_t* const TWI) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
static inline void TWI_StopTransmission(TWI_t* const TWI)
{
TWI->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc;
}
/* Function Prototypes: */
/** Begins a master mode TWI bus communication with the given slave device address.
*
* \param[in] TWI Pointer to the base of the TWI peripheral within the device.
* \param[in] SlaveAddress Address of the slave TWI device to communicate with.
* \param[in] TimeoutMS Timeout period within which the slave must respond, in milliseconds.
*
* \return A value from the \ref TWI_ErrorCodes_t enum.
*/
uint8_t TWI_StartTransmission(TWI_t* const TWI,
const uint8_t SlaveAddress,
const uint8_t TimeoutMS) ATTR_NON_NULL_PTR_ARG(1);
/** Sends a byte to the currently addressed device on the TWI bus.
*
* \param[in] TWI Pointer to the base of the TWI peripheral within the device.
* \param[in] Byte Byte to send to the currently addressed device
*
* \return Boolean \c true if the recipient ACKed the byte, \c false otherwise
*/
bool TWI_SendByte(TWI_t* const TWI,
const uint8_t Byte) ATTR_NON_NULL_PTR_ARG(1);
/** Receives a byte from the currently addressed device on the TWI bus.
*
* \param[in] TWI Pointer to the base of the TWI peripheral within the device.
* \param[in] Byte Location where the read byte is to be stored.
* \param[in] LastByte Indicates if the byte should be ACKed if false, NAKed if true.
*
* \return Boolean \c true if the byte reception successfully completed, \c false otherwise.
*/
bool TWI_ReceiveByte(TWI_t* const TWI,
uint8_t* const Byte,
const bool LastByte) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
/** High level function to perform a complete packet transfer over the TWI bus to the specified
* device.
*
* \param[in] TWI Pointer to the base of the TWI peripheral within the device.
* \param[in] SlaveAddress Base address of the TWI slave device to communicate with.
* \param[in] TimeoutMS Timeout for bus capture and slave START ACK, in milliseconds.
* \param[in] InternalAddress Pointer to a location where the internal slave read start address is stored.
* \param[in] InternalAddressLen Size of the internal device address, in bytes.
* \param[in] Buffer Pointer to a buffer where the read packet data is to be stored.
* \param[in] Length Size of the packet to read, in bytes.
*
* \return A value from the \ref TWI_ErrorCodes_t enum.
*/
uint8_t TWI_ReadPacket(TWI_t* const TWI,
const uint8_t SlaveAddress,
const uint8_t TimeoutMS,
const uint8_t* InternalAddress,
uint8_t InternalAddressLen,
uint8_t* Buffer,
uint8_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(4);
/** High level function to perform a complete packet transfer over the TWI bus from the specified
* device.
*
* \param[in] TWI Pointer to the base of the TWI peripheral within the device.
* \param[in] SlaveAddress Base address of the TWI slave device to communicate with
* \param[in] TimeoutMS Timeout for bus capture and slave START ACK, in milliseconds
* \param[in] InternalAddress Pointer to a location where the internal slave write start address is stored
* \param[in] InternalAddressLen Size of the internal device address, in bytes
* \param[in] Buffer Pointer to a buffer where the packet data to send is stored
* \param[in] Length Size of the packet to send, in bytes
*
* \return A value from the \ref TWI_ErrorCodes_t enum.
*/
uint8_t TWI_WritePacket(TWI_t* const TWI,
const uint8_t SlaveAddress,
const uint8_t TimeoutMS,
const uint8_t* InternalAddress,
uint8_t InternalAddressLen,
const uint8_t* Buffer,
uint8_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(4);
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif
#endif
/** @} */