Compare commits

...

43 Commits

Author SHA1 Message Date
925bb56f98 Added clang format file 2019-08-02 19:44:34 +02:00
a3d76a138d Implemented peeking with and without data for interrupt and blocking mode 2019-08-02 18:20:06 +02:00
95963295e2 Implemented blocking rx 2019-08-02 17:54:34 +02:00
0bfd303a26 Removed unneeded tx complete interrupt 2019-08-02 17:41:14 +02:00
16f4be8c6c Implemented interrupt driven rx for uart0 2019-08-02 17:38:00 +02:00
efe1446907 Implemented interrupt driven rx for uart1 2019-08-02 17:36:07 +02:00
b90da9bd9c Moved ring buffer to it's own struct 2019-08-02 17:13:53 +02:00
51a9d30c0a Implemented interrupt driven tx 2019-08-02 16:41:53 +02:00
496bb3d4d1 Removed force inlining functions that would be called often 2019-08-02 16:41:34 +02:00
5d6bc4761c Changed interrupt order to match vector numbers 2019-08-02 15:46:07 +02:00
3aeb43ee1e Added basic structure to support interrupt driven operation 2019-08-02 12:18:35 +02:00
a13a1ca9ab Fixed header includes 2019-08-02 12:18:35 +02:00
bdf4bd169e Moved hardware abstraction to separate header 2019-08-02 12:18:35 +02:00
6e45340993 Removed trailing whitespaces 2019-08-01 21:51:46 +02:00
f0a3cd6da8 Improved formatting 2019-07-30 21:51:13 +02:00
6861b8f5d1 Added force inline to reduce code size 2019-07-30 21:48:00 +02:00
aac73447b3 Implemented hardware abstraction that both hardware0 and hardware1 can use 2019-07-30 21:43:52 +02:00
fbd087808a Added enums for register bit positions 2019-07-30 20:56:16 +02:00
65bbf5e96a Refactored hardware abstraction 2019-07-30 20:29:38 +02:00
c03196493a Ran clang-format 2019-07-30 20:29:15 +02:00
470eb06345 Removed unused struct 2019-07-30 18:35:45 +02:00
099be106a7 Added C uart library by Peter Fleury as comparison 2019-07-30 18:32:00 +02:00
6ded0e1c8d Fixed rounding error in baud rate calculation 2019-07-28 19:20:03 +02:00
00cb9ad13c Added alias for first hardware uart 2019-07-28 17:58:23 +02:00
4a9cee922a Refactored class names to start with capital letter 2019-07-28 17:57:49 +02:00
8e0ba5a463 Implemented basic hardware support for transmitting 2019-07-28 17:32:51 +02:00
a71035d4b7 Specified default for hardware mode 2019-07-28 14:10:48 +02:00
fd7e8e7238 Added driving parameter 2019-07-28 14:09:09 +02:00
d9a05d0273 Fixed refactoring problem 2019-07-28 14:08:41 +02:00
2bbba0fcbd Removed unnecessary const qualifiers in template 2019-07-28 14:00:46 +02:00
29b4d85ce3 Renamed settings to config 2019-07-28 12:15:19 +02:00
ae90fdae3f Renamed choosing function 2019-07-28 10:54:47 +02:00
2364bff11f Implemented automatic type deducation depending on data bits 2019-07-28 10:49:14 +02:00
f08f607265 Fixed not implemented compiler error 2019-07-28 10:35:11 +02:00
f9c34b09ba Added basic layout for new library implementation 2019-07-27 18:55:17 +02:00
e07ba7ecd8 Fixed handling for ATmega1284P 2019-07-27 18:54:51 +02:00
81e6a9fdc0 Added support for atmega8a 2018-04-12 10:44:03 +02:00
b2a3b03867 Added git ignore and attribute files 2016-08-16 16:46:33 +02:00
88eb11cc02 Added blocking receive function and peek function 2016-05-26 20:15:21 +02:00
7fd6d8ddec Added separate receive line function with timeout and removed terminating string from received line 2016-05-25 23:38:02 +02:00
c261d7d309 Added getter functions for usart settings and fixed receive flush to work for all usart settings 2016-05-25 21:22:16 +02:00
e008cc8da1 Fixed flushing receive buffer to work independent of baud rate and with and without interrupts 2016-05-25 01:40:53 +02:00
99d09b0f0f Converted to submodule 2016-05-24 21:11:44 +02:00
17 changed files with 2160 additions and 360 deletions

13
.clang-format Normal file
View File

@@ -0,0 +1,13 @@
---
BasedOnStyle: LLVM
ColumnLimit: 120
IndentWidth: 4
TabWidth: 4
UseTab: ForIndentation
AlignEscapedNewlines: DontAlign
AllowShortFunctionsOnASingleLine: Empty
AlwaysBreakTemplateDeclarations: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterFunction: true
...

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "usart/array"]
path = usart/array
url = git@blackmark.me:array.git

48
config.hpp Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
namespace uart {
enum class DataBits {
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
};
enum class StopBits {
ONE,
TWO,
};
enum class Parity {
NONE,
ODD,
EVEN,
};
namespace detail {
template <DataBits dataBits>
struct choose_data_type {
using type = uint8_t;
};
template <>
struct choose_data_type<DataBits::NINE> {
using type = uint16_t;
};
} // namespace detail
template <uint32_t baudRate = 9600, DataBits dataBits = DataBits::EIGHT, Parity parity = Parity::NONE,
StopBits stopBits = StopBits::ONE>
struct Config {
static constexpr auto BAUD_RATE = baudRate;
static constexpr auto DATA_BITS = dataBits;
static constexpr auto PARITY = parity;
static constexpr auto STOP_BITS = stopBits;
using data_t = typename detail::choose_data_type<DATA_BITS>::type;
};
} // namespace uart

213
hardware.hpp Normal file
View File

@@ -0,0 +1,213 @@
#pragma once
#define FORCE_INLINE __attribute__((always_inline))
namespace uart {
enum class Mode {
ASYNCHRONOUS,
ASYNCHRONOUS_2X,
SYNCHRONOUS_MASTER,
SYNCHRONOUS_SLAVE,
SPI,
};
enum class Driven {
INTERRUPT,
BLOCKING,
};
namespace detail {
template <class Registers, typename CtrlFlagsA, typename CtrlFlagsB, typename CtrlFlagsC, class cfg, Mode mode,
Driven driven>
class Hardware {
public:
static void init() FORCE_INLINE
{
constexpr auto baudVal = calcBaud();
*Registers::BAUD_REG_H = static_cast<uint8_t>(baudVal >> 8);
*Registers::BAUD_REG_L = static_cast<uint8_t>(baudVal);
constexpr auto dataBitsVal = calcDataBits();
constexpr auto parityVal = calcParity();
constexpr auto stopBitsVal = calcStopBits();
constexpr auto modeVal = calcMode();
constexpr auto enableRx = calcRxState<true>();
constexpr auto enableTx = calcTxState<true>();
constexpr auto interruptVal = calcInterrupt();
constexpr uint8_t controlRegB = dataBitsVal.regBVal | enableRx | enableTx | interruptVal;
constexpr uint8_t controlRegC = dataBitsVal.regCVal | parityVal | stopBitsVal | modeVal;
*Registers::CTRL_STAT_REG_B = controlRegB;
*Registers::CTRL_STAT_REG_C = controlRegC;
}
static bool rxByteBlocking(typename cfg::data_t &byte) FORCE_INLINE
{
if (*Registers::CTRL_STAT_REG_A & (1 << CtrlFlagsA::RECEIVE_COMPLETE)) {
byte = *Registers::IO_REG;
return true;
}
return false;
}
static typename cfg::data_t rxByteInterrupt() FORCE_INLINE
{
return *Registers::IO_REG;
}
static void txByteBlocking(const typename cfg::data_t &byte) FORCE_INLINE
{
while (!(*Registers::CTRL_STAT_REG_A & (1 << CtrlFlagsA::DATA_REG_EMPTY)))
;
*Registers::IO_REG = byte;
}
static void txByteInterrupt(volatile const typename cfg::data_t &byte) FORCE_INLINE
{
*Registers::IO_REG = byte;
}
static bool peekBlocking() FORCE_INLINE
{
if (*Registers::CTRL_STAT_REG_A & (1 << CtrlFlagsA::RECEIVE_COMPLETE)) {
return true;
}
return false;
}
static void enableDataRegEmptyInt() FORCE_INLINE
{
*Registers::CTRL_STAT_REG_B |= (1 << CtrlFlagsB::DATA_REG_EMPTY_INT_ENABLE);
}
static void disableDataRegEmptyInt() FORCE_INLINE
{
*Registers::CTRL_STAT_REG_B &= ~(1 << CtrlFlagsB::DATA_REG_EMPTY_INT_ENABLE);
}
private:
struct DataBitsVal {
uint8_t regCVal = 0;
uint8_t regBVal = 0;
};
static constexpr auto calcBaud()
{
// The actual formula is (F_CPU / (16 * baudRate)) - 1, but this one has the advantage of rounding correctly
constexpr auto baudVal = (F_CPU + 8 * cfg::BAUD_RATE) / (16 * cfg::BAUD_RATE) - 1;
return baudVal;
}
static constexpr auto calcDataBits()
{
DataBitsVal dataBitsVal;
switch (cfg::DATA_BITS) {
case DataBits::FIVE:
dataBitsVal.regCVal = 0;
break;
case DataBits::SIX:
dataBitsVal.regCVal = (1 << CtrlFlagsC::CHAR_SIZE_0);
break;
case DataBits::SEVEN:
dataBitsVal.regCVal = (1 << CtrlFlagsC::CHAR_SIZE_1);
break;
case DataBits::EIGHT:
dataBitsVal.regCVal = (1 << CtrlFlagsC::CHAR_SIZE_1) | (1 << CtrlFlagsC::CHAR_SIZE_0);
break;
case DataBits::NINE:
dataBitsVal.regCVal = (1 << CtrlFlagsC::CHAR_SIZE_1) | (1 << CtrlFlagsC::CHAR_SIZE_0);
dataBitsVal.regBVal = (1 << CtrlFlagsB::CHAR_SIZE_2);
break;
}
return dataBitsVal;
}
static constexpr auto calcParity()
{
uint8_t parityVal = 0;
if (cfg::PARITY == Parity::EVEN)
parityVal = (1 << CtrlFlagsC::PARITY_MODE_1);
else if (cfg::PARITY == Parity::ODD)
parityVal = (1 << CtrlFlagsC::PARITY_MODE_1) | (1 << CtrlFlagsC::PARITY_MODE_0);
return parityVal;
}
static constexpr auto calcStopBits()
{
uint8_t stopBitsVal = 0;
if (cfg::STOP_BITS == StopBits::TWO)
stopBitsVal = (1 << CtrlFlagsC::STOP_BIT_SEL);
return stopBitsVal;
}
static constexpr auto calcMode()
{
static_assert(mode != Mode::SPI, "SPI mode can not be used with uart");
uint8_t modeVal = 0;
if (mode == Mode::SYNCHRONOUS_MASTER || mode == Mode::SYNCHRONOUS_SLAVE) {
modeVal = (1 << CtrlFlagsC::MODE_SEL_0);
}
return modeVal;
}
template <bool enable>
static constexpr auto calcRxState()
{
uint8_t enableVal = 0;
if (enable)
enableVal = (1 << CtrlFlagsB::RX_ENABLE);
return enableVal;
}
template <bool enable>
static constexpr auto calcTxState()
{
uint8_t enableVal = 0;
if (enable)
enableVal = (1 << CtrlFlagsB::TX_ENABLE);
return enableVal;
}
static constexpr auto calcInterrupt()
{
uint8_t interruptVal = 0;
if (driven == Driven::INTERRUPT)
interruptVal |= (1 << CtrlFlagsB::DATA_REG_EMPTY_INT_ENABLE) | (1 << CtrlFlagsB::RX_INT_ENABLE);
return interruptVal;
}
};
template <typename data_t, uint8_t Size>
struct RingBuffer {
uint8_t head;
uint8_t tail;
data_t buf[Size];
};
} // namespace detail
} // namespace uart
#undef FORCE_INLINE

218
hardware0.hpp Normal file
View File

@@ -0,0 +1,218 @@
#pragma once
#include "config.hpp"
#include "hardware.hpp"
#define FORCE_INLINE __attribute__((always_inline))
namespace uart {
namespace detail {
#if defined(__AVR_ATmega1284P__)
struct Registers0 {
static constexpr volatile auto *IO_REG = &UDR0;
static constexpr volatile auto *CTRL_STAT_REG_A = &UCSR0A;
static constexpr volatile auto *CTRL_STAT_REG_B = &UCSR0B;
static constexpr volatile auto *CTRL_STAT_REG_C = &UCSR0C;
static constexpr volatile auto *BAUD_REG_L = &UBRR0L;
static constexpr volatile auto *BAUD_REG_H = &UBRR0H;
};
enum class ControlFlagsA0 {
MULTI_PROC_COMM_MODE = MPCM0,
SPEED_2X = U2X0,
PARITY_ERROR = UPE0,
DATA_OVER_RUN = DOR0,
FRAME_ERROR = FE0,
DATA_REG_EMPTY = UDRE0,
TRANSMIT_COMPLETE = TXC0,
RECEIVE_COMPLETE = RXC0,
};
enum class ControlFlagsB0 {
TX_DATA_BIT_8 = TXB80,
RX_DATA_BIT_8 = RXB80,
CHAR_SIZE_2 = UCSZ02,
TX_ENABLE = TXEN0,
RX_ENABLE = RXEN0,
DATA_REG_EMPTY_INT_ENABLE = UDRIE0,
TX_INT_ENABLE = TXCIE0,
RX_INT_ENABLE = RXCIE0,
};
enum class ControlFlagsC0 {
CLK_POLARITY = UCPOL0,
CHAR_SIZE_0 = UCSZ00,
CHAR_SIZE_1 = UCSZ01,
STOP_BIT_SEL = USBS0,
PARITY_MODE_0 = UPM00,
PARITY_MODE_1 = UPM01,
MODE_SEL_0 = UMSEL00,
MODE_SEL_1 = UMSEL01,
};
// clang-format off
constexpr int operator<<(const int &lhs, const ControlFlagsA0 &rhs) { return lhs << static_cast<int>(rhs); }
constexpr int operator<<(const int &lhs, const ControlFlagsB0 &rhs) { return lhs << static_cast<int>(rhs); }
constexpr int operator<<(const int &lhs, const ControlFlagsC0 &rhs) { return lhs << static_cast<int>(rhs); }
// clang-format on
static void (*fnRx0IntHandler)() = nullptr;
static void (*fnDataReg0EmptyIntHandler)() = nullptr;
ISR(USART0_RX_vect)
{
if (fnRx0IntHandler)
fnRx0IntHandler();
}
ISR(USART0_UDRE_vect)
{
if (fnDataReg0EmptyIntHandler)
fnDataReg0EmptyIntHandler();
}
#else
#error "This chip is not supported"
#endif
} // namespace detail
template <Mode mode = Mode::ASYNCHRONOUS, class cfg = Config<>, Driven driven = Driven::INTERRUPT>
class Hardware0 {
public:
using data_t = typename cfg::data_t;
static constexpr auto DATA_BITS = cfg::DATA_BITS;
static void init() FORCE_INLINE
{
HardwareImpl::init();
}
static void txByte(data_t byte) FORCE_INLINE
{
HardwareImpl::txByteBlocking(byte);
}
static bool rxByte(data_t &byte) FORCE_INLINE
{
return HardwareImpl::rxByteBlocking(byte);
}
static bool peek(data_t &byte) FORCE_INLINE
{
static_cast<void>(byte);
static_assert(driven == Driven::BLOCKING, "Peek with data is not supported in blocking mode");
return false;
}
static bool peek() FORCE_INLINE
{
return HardwareImpl::peekBlocking();
}
private:
using HardwareImpl = detail::Hardware<detail::Registers0, detail::ControlFlagsA0, detail::ControlFlagsB0,
detail::ControlFlagsC0, cfg, mode, driven>;
};
template <Mode mode, class cfg>
class Hardware0<mode, cfg, Driven::INTERRUPT> {
public:
using data_t = typename cfg::data_t;
static constexpr auto DATA_BITS = cfg::DATA_BITS;
static void init() FORCE_INLINE
{
detail::fnRx0IntHandler = rxIntHandler;
detail::fnDataReg0EmptyIntHandler = dataRegEmptyIntHandler;
HardwareImpl::init();
}
static void txByte(const data_t &byte) FORCE_INLINE
{
uint8_t tmpHead = (sm_txBuf.head + 1) % TX_BUFFER_SIZE;
while (tmpHead == sm_txBuf.tail)
;
sm_txBuf.buf[tmpHead] = byte;
sm_txBuf.head = tmpHead;
HardwareImpl::enableDataRegEmptyInt();
}
static bool rxByte(data_t &byte) FORCE_INLINE
{
if (sm_rxBuf.head == sm_rxBuf.tail)
return false;
uint8_t tmpTail = (sm_rxBuf.tail + 1) % RX_BUFFER_SIZE;
byte = sm_rxBuf.buf[tmpTail];
sm_rxBuf.tail = tmpTail;
return true;
}
static bool peek(data_t &byte) FORCE_INLINE
{
if (sm_rxBuf.head == sm_rxBuf.tail)
return false;
uint8_t tmpTail = (sm_rxBuf.tail + 1) % RX_BUFFER_SIZE;
byte = sm_rxBuf.buf[tmpTail];
return true;
}
static bool peek() FORCE_INLINE
{
return (sm_rxBuf.head != sm_rxBuf.tail);
}
private:
using HardwareImpl = detail::Hardware<detail::Registers0, detail::ControlFlagsA0, detail::ControlFlagsB0,
detail::ControlFlagsC0, cfg, mode, Driven::INTERRUPT>;
static constexpr auto TX_BUFFER_SIZE = 16;
static constexpr auto RX_BUFFER_SIZE = 16;
static volatile detail::RingBuffer<data_t, TX_BUFFER_SIZE> sm_txBuf;
static volatile detail::RingBuffer<data_t, RX_BUFFER_SIZE> sm_rxBuf;
static void rxIntHandler()
{
uint8_t tmpHead = (sm_rxBuf.head + 1) % RX_BUFFER_SIZE;
if (tmpHead != sm_rxBuf.tail) {
sm_rxBuf.head = tmpHead;
sm_rxBuf.buf[tmpHead] = HardwareImpl::rxByteInterrupt();
}
}
static void dataRegEmptyIntHandler() FORCE_INLINE
{
if (sm_txBuf.head != sm_txBuf.tail) {
uint8_t tmpTail = (sm_txBuf.tail + 1) % TX_BUFFER_SIZE;
sm_txBuf.tail = tmpTail;
HardwareImpl::txByteInterrupt(sm_txBuf.buf[tmpTail]);
} else
HardwareImpl::disableDataRegEmptyInt();
}
};
template <Mode mode, class cfg>
volatile detail::RingBuffer<typename Hardware0<mode, cfg, Driven::INTERRUPT>::data_t,
Hardware0<mode, cfg, Driven::INTERRUPT>::TX_BUFFER_SIZE>
Hardware0<mode, cfg, Driven::INTERRUPT>::sm_txBuf = {0, 0, {0}};
template <Mode mode, class cfg>
volatile detail::RingBuffer<typename Hardware0<mode, cfg, Driven::INTERRUPT>::data_t,
Hardware0<mode, cfg, Driven::INTERRUPT>::RX_BUFFER_SIZE>
Hardware0<mode, cfg, Driven::INTERRUPT>::sm_rxBuf = {0, 0, {0}};
} // namespace uart
#undef FORCE_INLINE

224
hardware1.hpp Normal file
View File

@@ -0,0 +1,224 @@
#pragma once
#include "config.hpp"
#include "hardware.hpp"
#define FORCE_INLINE __attribute__((always_inline))
namespace uart {
namespace detail {
#if defined(__AVR_ATmega1284P__)
struct Registers1 {
static constexpr volatile auto *IO_REG = &UDR1;
static constexpr volatile auto *CTRL_STAT_REG_A = &UCSR1A;
static constexpr volatile auto *CTRL_STAT_REG_B = &UCSR1B;
static constexpr volatile auto *CTRL_STAT_REG_C = &UCSR1C;
static constexpr volatile auto *BAUD_REG_L = &UBRR1L;
static constexpr volatile auto *BAUD_REG_H = &UBRR1H;
};
enum class ControlFlagsA1 {
MULTI_PROC_COMM_MODE = MPCM1,
SPEED_2X = U2X1,
PARITY_ERROR = UPE1,
DATA_OVER_RUN = DOR1,
FRAME_ERROR = FE1,
DATA_REG_EMPTY = UDRE1,
TRANSMIT_COMPLETE = TXC1,
RECEIVE_COMPLETE = RXC1,
};
enum class ControlFlagsB1 {
TX_DATA_BIT_8 = TXB81,
RX_DATA_BIT_8 = RXB81,
CHAR_SIZE_2 = UCSZ12,
TX_ENABLE = TXEN1,
RX_ENABLE = RXEN1,
DATA_REG_EMPTY_INT_ENABLE = UDRIE1,
TX_INT_ENABLE = TXCIE1,
RX_INT_ENABLE = RXCIE1,
};
enum class ControlFlagsC1 {
CLK_POLARITY = UCPOL1,
CHAR_SIZE_0 = UCSZ10,
CHAR_SIZE_1 = UCSZ11,
STOP_BIT_SEL = USBS1,
PARITY_MODE_0 = UPM10,
PARITY_MODE_1 = UPM11,
MODE_SEL_0 = UMSEL10,
MODE_SEL_1 = UMSEL11,
};
// clang-format off
constexpr int operator<<(const int &lhs, const ControlFlagsA1 &rhs) { return lhs << static_cast<int>(rhs); }
constexpr int operator<<(const int &lhs, const ControlFlagsB1 &rhs) { return lhs << static_cast<int>(rhs); }
constexpr int operator<<(const int &lhs, const ControlFlagsC1 &rhs) { return lhs << static_cast<int>(rhs); }
// clang-format on
static void (*fnRx1IntHandler)() = nullptr;
static void (*fnDataReg1EmptyIntHandler)() = nullptr;
ISR(USART1_RX_vect)
{
if (fnRx1IntHandler)
fnRx1IntHandler();
}
ISR(USART1_UDRE_vect)
{
if (fnDataReg1EmptyIntHandler)
fnDataReg1EmptyIntHandler();
}
#define HAS_UART1
#else
#error "This chip is not supported"
#endif
} // namespace detail
#ifdef HAS_UART1
template <Mode mode = Mode::ASYNCHRONOUS, class cfg = Config<>, Driven driven = Driven::INTERRUPT>
class Hardware1 {
public:
using data_t = typename cfg::data_t;
static constexpr auto DATA_BITS = cfg::DATA_BITS;
static void init() FORCE_INLINE
{
HardwareImpl::init();
}
static void txByte(const data_t &byte) FORCE_INLINE
{
HardwareImpl::txByteBlocking(byte);
}
static bool rxByte(data_t &byte) FORCE_INLINE
{
return HardwareImpl::rxByteBlocking(byte);
}
static bool peek(data_t &byte) FORCE_INLINE
{
static_cast<void>(byte);
static_assert(driven != Driven::BLOCKING, "Peek with data is not supported in blocking mode");
return false;
}
static bool peek() FORCE_INLINE
{
return HardwareImpl::peekBlocking();
}
private:
using HardwareImpl = detail::Hardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
detail::ControlFlagsC1, cfg, mode, driven>;
};
template <Mode mode, class cfg>
class Hardware1<mode, cfg, Driven::INTERRUPT> {
public:
using data_t = typename cfg::data_t;
static constexpr auto DATA_BITS = cfg::DATA_BITS;
static void init() FORCE_INLINE
{
detail::fnRx1IntHandler = rxIntHandler;
detail::fnDataReg1EmptyIntHandler = dataRegEmptyIntHandler;
HardwareImpl::init();
}
static void txByte(const data_t &byte) FORCE_INLINE
{
uint8_t tmpHead = (sm_txBuf.head + 1) % TX_BUFFER_SIZE;
while (tmpHead == sm_txBuf.tail)
;
sm_txBuf.buf[tmpHead] = byte;
sm_txBuf.head = tmpHead;
HardwareImpl::enableDataRegEmptyInt();
}
static bool rxByte(data_t &byte) FORCE_INLINE
{
if (sm_rxBuf.head == sm_rxBuf.tail)
return false;
uint8_t tmpTail = (sm_rxBuf.tail + 1) % RX_BUFFER_SIZE;
byte = sm_rxBuf.buf[tmpTail];
sm_rxBuf.tail = tmpTail;
return true;
}
static bool peek(data_t &byte) FORCE_INLINE
{
if (sm_rxBuf.head == sm_rxBuf.tail)
return false;
uint8_t tmpTail = (sm_rxBuf.tail + 1) % RX_BUFFER_SIZE;
byte = sm_rxBuf.buf[tmpTail];
return true;
}
static bool peek() FORCE_INLINE
{
return (sm_rxBuf.head != sm_rxBuf.tail);
}
private:
using HardwareImpl = detail::Hardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
detail::ControlFlagsC1, cfg, mode, Driven::INTERRUPT>;
static constexpr auto TX_BUFFER_SIZE = 16;
static constexpr auto RX_BUFFER_SIZE = 16;
static volatile detail::RingBuffer<data_t, TX_BUFFER_SIZE> sm_txBuf;
static volatile detail::RingBuffer<data_t, RX_BUFFER_SIZE> sm_rxBuf;
static void rxIntHandler()
{
uint8_t tmpHead = (sm_rxBuf.head + 1) % RX_BUFFER_SIZE;
if (tmpHead != sm_rxBuf.tail) {
sm_rxBuf.head = tmpHead;
sm_rxBuf.buf[tmpHead] = HardwareImpl::rxByteInterrupt();
}
}
static void dataRegEmptyIntHandler() FORCE_INLINE
{
if (sm_txBuf.head != sm_txBuf.tail) {
uint8_t tmpTail = (sm_txBuf.tail + 1) % TX_BUFFER_SIZE;
sm_txBuf.tail = tmpTail;
HardwareImpl::txByteInterrupt(sm_txBuf.buf[tmpTail]);
} else
HardwareImpl::disableDataRegEmptyInt();
}
};
template <Mode mode, class cfg>
volatile detail::RingBuffer<typename Hardware1<mode, cfg, Driven::INTERRUPT>::data_t,
Hardware1<mode, cfg, Driven::INTERRUPT>::TX_BUFFER_SIZE>
Hardware1<mode, cfg, Driven::INTERRUPT>::sm_txBuf = {0, 0, {0}};
template <Mode mode, class cfg>
volatile detail::RingBuffer<typename Hardware1<mode, cfg, Driven::INTERRUPT>::data_t,
Hardware1<mode, cfg, Driven::INTERRUPT>::RX_BUFFER_SIZE>
Hardware1<mode, cfg, Driven::INTERRUPT>::sm_rxBuf = {0, 0, {0}};
#endif
} // namespace uart
#undef FORCE_INLINE

18
software.hpp Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
#include "config.hpp"
#include "../io/io.hpp"
namespace uart {
template <io::P rxPin, io::P txPin, class cfg = Config<>>
class Software {
public:
using data_t = typename cfg::data_t;
static constexpr auto DATA_BITS = cfg::DATA_BITS;
static void init() {}
};
} // namespace uart

754
uart.cpp Normal file
View File

@@ -0,0 +1,754 @@
/*************************************************************************
Title: Interrupt UART library with receive/transmit circular buffers
Author: Peter Fleury <pfleury@gmx.ch> http://tinyurl.com/peterfleury
File: $Id: uart.c,v 1.15.2.4 2015/09/05 18:33:32 peter Exp $
Software: AVR-GCC 4.x
Hardware: any AVR with built-in UART,
License: GNU General Public License
DESCRIPTION:
An interrupt is generated when the UART has finished transmitting or
receiving a byte. The interrupt handling routines use circular buffers
for buffering received and transmitted data.
The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
the buffer size in bytes. Note that these variables must be a
power of 2.
USAGE:
Refere to the header file uart.h for a description of the routines.
See also example test_uart.c.
NOTES:
Based on Atmel Application Note AVR306
LICENSE:
Copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*************************************************************************/
#include "uart.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
/*
* constants and macros
*/
/* size of RX/TX buffers */
#define UART_RX_BUFFER_MASK (UART_RX_BUFFER_SIZE - 1)
#define UART_TX_BUFFER_MASK (UART_TX_BUFFER_SIZE - 1)
#if (UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK)
#error RX buffer size is not a power of 2
#endif
#if (UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK)
#error TX buffer size is not a power of 2
#endif
#if defined(__AVR_AT90S2313__) || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || \
defined(__AVR_AT90S4434__) || defined(__AVR_AT90S8535__) || defined(__AVR_ATmega103__)
/* old AVR classic or ATmega103 with one UART */
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS USR
#define UART0_CONTROL UCR
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRR
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
/* old AVR classic with one UART */
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRR
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#elif defined(__AVR_AT90PWM216__) || defined(__AVR_AT90PWM316__)
/* AT90PWN216/316 with one USART */
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega8A__) || defined(__AVR_ATmega16__) || \
defined(__AVR_ATmega16A__) || defined(__AVR_ATmega32__) || defined(__AVR_ATmega32A__) || \
defined(__AVR_ATmega323__)
/* ATmega with one USART */
#define UART0_RECEIVE_INTERRUPT USART_RXC_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#define UART0_BIT_URSEL URSEL
#elif defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#define UART0_BIT_URSEL URSEL
#elif defined(__AVR_ATmega163__)
/* ATmega163 with one UART */
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRR
#define UART0_UBRRH UBRRHI
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#elif defined(__AVR_ATmega162__)
/* ATmega with two USART */
#define ATMEGA_USART1
#define UART0_RECEIVE_INTERRUPT USART0_RXC_vect
#define UART1_RECEIVE_INTERRUPT USART1_RXC_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROLC UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART0_UBRRL UBRR0L
#define UART0_UBRRH UBRR0H
#define UART0_BIT_URSEL URSEL0
#define UART0_BIT_U2X U2X0
#define UART0_BIT_RXCIE RXCIE0
#define UART0_BIT_RXEN RXEN0
#define UART0_BIT_TXEN TXEN0
#define UART0_BIT_UCSZ0 UCSZ00
#define UART0_BIT_UCSZ1 UCSZ01
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_CONTROLC UCSR1C
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1
#define UART1_UBRRL UBRR1L
#define UART1_UBRRH UBRR1H
#define UART1_BIT_URSEL URSEL1
#define UART1_BIT_U2X U2X1
#define UART1_BIT_RXCIE RXCIE1
#define UART1_BIT_RXEN RXEN1
#define UART1_BIT_TXEN TXEN1
#define UART1_BIT_UCSZ0 UCSZ10
#define UART1_BIT_UCSZ1 UCSZ11
#elif defined(__AVR_ATmega161__)
/* ATmega with UART */
#error "AVR ATmega161 currently not supported by this libaray !"
#elif defined(__AVR_ATmega169__)
/* ATmega with one USART */
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48P__) || \
defined(__AVR_ATmega48PA__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88__) || \
defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PA__) || \
defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || \
defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || \
defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega3250__) || \
defined(__AVR_ATmega3290__) || defined(__AVR_ATmega6450__) || defined(__AVR_ATmega6490__)
/* ATmega with one USART */
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROLC UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART0_UBRRL UBRR0L
#define UART0_UBRRH UBRR0H
#define UART0_BIT_U2X U2X0
#define UART0_BIT_RXCIE RXCIE0
#define UART0_BIT_RXEN RXEN0
#define UART0_BIT_TXEN TXEN0
#define UART0_BIT_UCSZ0 UCSZ00
#define UART0_BIT_UCSZ1 UCSZ01
#elif defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny2313A__) || defined(__AVR_ATtiny4313__)
/* ATtiny with one USART */
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_CONTROLC UCSRC
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#define UART0_UBRRL UBRRL
#define UART0_UBRRH UBRRH
#define UART0_BIT_U2X U2X
#define UART0_BIT_RXCIE RXCIE
#define UART0_BIT_RXEN RXEN
#define UART0_BIT_TXEN TXEN
#define UART0_BIT_UCSZ0 UCSZ0
#define UART0_BIT_UCSZ1 UCSZ1
#elif defined(__AVR_ATmega329__) || defined(__AVR_ATmega649__) || defined(__AVR_ATmega3290__) || \
defined(__AVR_ATmega6490__) || defined(__AVR_ATmega169A__) || defined(__AVR_ATmega169PA__) || \
defined(__AVR_ATmega329A__) || defined(__AVR_ATmega329PA__) || defined(__AVR_ATmega3290A__) || \
defined(__AVR_ATmega3290PA__) || defined(__AVR_ATmega649A__) || defined(__AVR_ATmega649P__) || \
defined(__AVR_ATmega6490A__) || defined(__AVR_ATmega6490P__) || defined(__AVR_ATmega165__) || \
defined(__AVR_ATmega325__) || defined(__AVR_ATmega645__) || defined(__AVR_ATmega3250__) || \
defined(__AVR_ATmega6450__) || defined(__AVR_ATmega165A__) || defined(__AVR_ATmega165PA__) || \
defined(__AVR_ATmega325A__) || defined(__AVR_ATmega325PA__) || defined(__AVR_ATmega3250A__) || \
defined(__AVR_ATmega3250PA__) || defined(__AVR_ATmega645A__) || defined(__AVR_ATmega645PA__) || \
defined(__AVR_ATmega6450A__) || defined(__AVR_ATmega6450PA__) || defined(__AVR_ATmega644__)
/* ATmega with one USART */
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROLC UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART0_UBRRL UBRR0L
#define UART0_UBRRH UBRR0H
#define UART0_BIT_U2X U2X0
#define UART0_BIT_RXCIE RXCIE0
#define UART0_BIT_RXEN RXEN0
#define UART0_BIT_TXEN TXEN0
#define UART0_BIT_UCSZ0 UCSZ00
#define UART0_BIT_UCSZ1 UCSZ01
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega128A__) || \
defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || \
defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega164P__) || \
defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega164A__) || \
defined(__AVR_ATmega164PA__) || defined(__AVR_ATmega324A__) || defined(__AVR_ATmega324PA__) || \
defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284__) || \
defined(__AVR_ATmega1284P__) || defined(__AVR_ATtiny1634__)
/* ATmega with two USART */
#define ATMEGA_USART1
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_CONTROLC UCSR0C
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART0_UBRRL UBRR0L
#define UART0_UBRRH UBRR0H
#define UART0_BIT_U2X U2X0
#define UART0_BIT_RXCIE RXCIE0
#define UART0_BIT_RXEN RXEN0
#define UART0_BIT_TXEN TXEN0
#define UART0_BIT_UCSZ0 UCSZ00
#define UART0_BIT_UCSZ1 UCSZ01
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_CONTROLC UCSR1C
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1
#define UART1_UBRRL UBRR1L
#define UART1_UBRRH UBRR1H
#define UART1_BIT_U2X U2X1
#define UART1_BIT_RXCIE RXCIE1
#define UART1_BIT_RXEN RXEN1
#define UART1_BIT_TXEN TXEN1
#define UART1_BIT_UCSZ0 UCSZ10
#define UART1_BIT_UCSZ1 UCSZ11
#elif defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || \
defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB82__) || \
defined(__AVR_AT90USB162__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || \
defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__)
#define UART0_RECEIVE_INTERRUPT USART1_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR1A
#define UART0_CONTROL UCSR1B
#define UART0_CONTROLC UCSR1C
#define UART0_DATA UDR1
#define UART0_UDRIE UDRIE1
#define UART0_UBRRL UBRR1L
#define UART0_UBRRH UBRR1H
#define UART0_BIT_U2X U2X1
#define UART0_BIT_RXCIE RXCIE1
#define UART0_BIT_RXEN RXEN1
#define UART0_BIT_TXEN TXEN1
#define UART0_BIT_UCSZ0 UCSZ10
#define UART0_BIT_UCSZ1 UCSZ11
#else
#error "no UART definition for MCU available"
#endif
/*
* module global variables
*/
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static volatile unsigned char UART_LastRxError;
#if defined(ATMEGA_USART1)
static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART1_TxHead;
static volatile unsigned char UART1_TxTail;
static volatile unsigned char UART1_RxHead;
static volatile unsigned char UART1_RxTail;
static volatile unsigned char UART1_LastRxError;
#endif
ISR(UART0_RECEIVE_INTERRUPT)
/*************************************************************************
Function: UART Receive Complete interrupt
Purpose: called when the UART has received a character
**************************************************************************/
{
unsigned char tmphead;
unsigned char data;
unsigned char usr;
unsigned char lastRxError;
/* read UART status register and UART data register */
usr = UART0_STATUS;
data = UART0_DATA;
/* get FEn (Frame Error) DORn (Data OverRun) UPEn (USART Parity Error) bits */
#if defined(FE) && defined(DOR) && defined(UPE)
lastRxError = usr & (_BV(FE) | _BV(DOR) | _BV(UPE));
#elif defined(FE0) && defined(DOR0) && defined(UPE0)
lastRxError = usr & (_BV(FE0) | _BV(DOR0) | _BV(UPE0));
#elif defined(FE1) && defined(DOR1) && defined(UPE1)
lastRxError = usr & (_BV(FE1) | _BV(DOR1) | _BV(UPE1));
#elif defined(FE) && defined(DOR)
lastRxError = usr & (_BV(FE) | _BV(DOR));
#endif
/* calculate buffer index */
tmphead = (UART_RxHead + 1) & UART_RX_BUFFER_MASK;
if (tmphead == UART_RxTail) {
/* error: receive buffer overflow */
lastRxError = UART_BUFFER_OVERFLOW >> 8;
} else {
/* store new index */
UART_RxHead = tmphead;
/* store received data in buffer */
UART_RxBuf[tmphead] = data;
}
UART_LastRxError |= lastRxError;
}
ISR(UART0_TRANSMIT_INTERRUPT)
/*************************************************************************
Function: UART Data Register Empty interrupt
Purpose: called when the UART is ready to transmit the next byte
**************************************************************************/
{
unsigned char tmptail;
if (UART_TxHead != UART_TxTail) {
/* calculate and store new buffer index */
tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
UART_TxTail = tmptail;
/* get one byte from buffer and write it to UART */
UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */
} else {
/* tx buffer empty, disable UDRE interrupt */
UART0_CONTROL &= ~_BV(UART0_UDRIE);
}
}
/*************************************************************************
Function: uart_init()
Purpose: initialize UART and set baudrate
Input: baudrate using macro UART_BAUD_SELECT()
Returns: none
**************************************************************************/
void uart_init(unsigned int baudrate)
{
UART_TxHead = 0;
UART_TxTail = 0;
UART_RxHead = 0;
UART_RxTail = 0;
#ifdef UART_TEST
#ifndef UART0_BIT_U2X
#warning "UART0_BIT_U2X not defined"
#endif
#ifndef UART0_UBRRH
#warning "UART0_UBRRH not defined"
#endif
#ifndef UART0_CONTROLC
#warning "UART0_CONTROLC not defined"
#endif
#if defined(URSEL) || defined(URSEL0)
#ifndef UART0_BIT_URSEL
#warning "UART0_BIT_URSEL not defined"
#endif
#endif
#endif
/* Set baud rate */
if (baudrate & 0x8000) {
#if UART0_BIT_U2X
UART0_STATUS = (1 << UART0_BIT_U2X); // Enable 2x speed
#endif
}
#if defined(UART0_UBRRH)
UART0_UBRRH = (unsigned char)((baudrate >> 8) & 0x80);
#endif
UART0_UBRRL = (unsigned char)(baudrate & 0x00FF);
/* Enable USART receiver and transmitter and receive complete interrupt */
UART0_CONTROL = _BV(UART0_BIT_RXCIE) | (1 << UART0_BIT_RXEN) | (1 << UART0_BIT_TXEN);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef UART0_CONTROLC
#ifdef UART0_BIT_URSEL
UART0_CONTROLC = (1 << UART0_BIT_URSEL) | (1 << UART0_BIT_UCSZ1) | (1 << UART0_BIT_UCSZ0);
#else
UART0_CONTROLC = (1 << UART0_BIT_UCSZ1) | (1 << UART0_BIT_UCSZ0);
#endif
#endif
} /* uart_init */
/*************************************************************************
Function: uart_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
unsigned int uart_getc(void)
{
unsigned char tmptail;
unsigned char data;
unsigned char lastRxError;
if (UART_RxHead == UART_RxTail) {
return UART_NO_DATA; /* no data available */
}
/* calculate buffer index */
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
/* get data from receive buffer */
data = UART_RxBuf[tmptail];
lastRxError = UART_LastRxError;
/* store buffer index */
UART_RxTail = tmptail;
UART_LastRxError = 0;
return (lastRxError << 8) + data;
} /* uart_getc */
/*************************************************************************
Function: uart_putc()
Purpose: write byte to ringbuffer for transmitting via UART
Input: byte to be transmitted
Returns: none
**************************************************************************/
void uart_putc(unsigned char data)
{
unsigned char tmphead;
tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
while (tmphead == UART_TxTail) {
; /* wait for free space in buffer */
}
UART_TxBuf[tmphead] = data;
UART_TxHead = tmphead;
/* enable UDRE interrupt */
UART0_CONTROL |= _BV(UART0_UDRIE);
} /* uart_putc */
/*************************************************************************
Function: uart_puts()
Purpose: transmit string to UART
Input: string to be transmitted
Returns: none
**************************************************************************/
void uart_puts(const char *s)
{
while (*s)
uart_putc(*s++);
} /* uart_puts */
/*************************************************************************
Function: uart_puts_p()
Purpose: transmit string from program memory to UART
Input: program memory string to be transmitted
Returns: none
**************************************************************************/
void uart_puts_p(const char *progmem_s)
{
register char c;
while ((c = pgm_read_byte(progmem_s++)))
uart_putc(c);
} /* uart_puts_p */
/*
* these functions are only for ATmegas with two USART
*/
#if defined(ATMEGA_USART1)
ISR(UART1_RECEIVE_INTERRUPT)
/*************************************************************************
Function: UART1 Receive Complete interrupt
Purpose: called when the UART1 has received a character
**************************************************************************/
{
unsigned char tmphead;
unsigned char data;
unsigned char usr;
unsigned char lastRxError;
/* read UART status register and UART data register */
usr = UART1_STATUS;
data = UART1_DATA;
/* get FEn (Frame Error) DORn (Data OverRun) UPEn (USART Parity Error) bits */
lastRxError = usr & (_BV(FE1) | _BV(DOR1) | _BV(UPE1));
/* calculate buffer index */
tmphead = (UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
if (tmphead == UART1_RxTail) {
/* error: receive buffer overflow */
lastRxError = UART_BUFFER_OVERFLOW >> 8;
} else {
/* store new index */
UART1_RxHead = tmphead;
/* store received data in buffer */
UART1_RxBuf[tmphead] = data;
}
UART1_LastRxError |= lastRxError;
}
ISR(UART1_TRANSMIT_INTERRUPT)
/*************************************************************************
Function: UART1 Data Register Empty interrupt
Purpose: called when the UART1 is ready to transmit the next byte
**************************************************************************/
{
unsigned char tmptail;
if (UART1_TxHead != UART1_TxTail) {
/* calculate and store new buffer index */
tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
UART1_TxTail = tmptail;
/* get one byte from buffer and write it to UART */
UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */
} else {
/* tx buffer empty, disable UDRE interrupt */
UART1_CONTROL &= ~_BV(UART1_UDRIE);
}
}
/*************************************************************************
Function: uart1_init()
Purpose: initialize UART1 and set baudrate
Input: baudrate using macro UART_BAUD_SELECT()
Returns: none
**************************************************************************/
void uart1_init(unsigned int baudrate)
{
UART1_TxHead = 0;
UART1_TxTail = 0;
UART1_RxHead = 0;
UART1_RxTail = 0;
#ifdef UART_TEST
#ifndef UART1_BIT_U2X
#warning "UART1_BIT_U2X not defined"
#endif
#ifndef UART1_UBRRH
#warning "UART1_UBRRH not defined"
#endif
#ifndef UART1_CONTROLC
#warning "UART1_CONTROLC not defined"
#endif
#if defined(URSEL) || defined(URSEL1)
#ifndef UART1_BIT_URSEL
#warning "UART1_BIT_URSEL not defined"
#endif
#endif
#endif
/* Set baud rate */
if (baudrate & 0x8000) {
#if UART1_BIT_U2X
UART1_STATUS = (1 << UART1_BIT_U2X); // Enable 2x speed
#endif
}
UART1_UBRRH = (unsigned char)((baudrate >> 8) & 0x80);
UART1_UBRRL = (unsigned char)baudrate;
/* Enable USART receiver and transmitter and receive complete interrupt */
UART1_CONTROL = _BV(UART1_BIT_RXCIE) | (1 << UART1_BIT_RXEN) | (1 << UART1_BIT_TXEN);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef UART1_BIT_URSEL
UART1_CONTROLC = (1 << UART1_BIT_URSEL) | (1 << UART1_BIT_UCSZ1) | (1 << UART1_BIT_UCSZ0);
#else
UART1_CONTROLC = (1 << UART1_BIT_UCSZ1) | (1 << UART1_BIT_UCSZ0);
#endif
} /* uart_init */
/*************************************************************************
Function: uart1_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
unsigned int uart1_getc(void)
{
unsigned char tmptail;
unsigned int data;
unsigned char lastRxError;
if (UART1_RxHead == UART1_RxTail) {
return UART_NO_DATA; /* no data available */
}
/* calculate buffer index */
tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
/* get data from receive buffer */
data = UART1_RxBuf[tmptail];
lastRxError = UART1_LastRxError;
/* store buffer index */
UART1_RxTail = tmptail;
UART1_LastRxError = 0;
return (lastRxError << 8) + data;
} /* uart1_getc */
/*************************************************************************
Function: uart1_putc()
Purpose: write byte to ringbuffer for transmitting via UART
Input: byte to be transmitted
Returns: none
**************************************************************************/
void uart1_putc(unsigned char data)
{
unsigned char tmphead;
tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
while (tmphead == UART1_TxTail) {
; /* wait for free space in buffer */
}
UART1_TxBuf[tmphead] = data;
UART1_TxHead = tmphead;
/* enable UDRE interrupt */
UART1_CONTROL |= _BV(UART1_UDRIE);
} /* uart1_putc */
/*************************************************************************
Function: uart1_puts()
Purpose: transmit string to UART1
Input: string to be transmitted
Returns: none
**************************************************************************/
void uart1_puts(const char *s)
{
while (*s)
uart1_putc(*s++);
} /* uart1_puts */
/*************************************************************************
Function: uart1_puts_p()
Purpose: transmit string from program memory to UART1
Input: program memory string to be transmitted
Returns: none
**************************************************************************/
void uart1_puts_p(const char *progmem_s)
{
register char c;
while ((c = pgm_read_byte(progmem_s++)))
uart1_putc(c);
} /* uart1_puts_p */
#endif

196
uart.h Normal file
View File

@@ -0,0 +1,196 @@
#ifndef UART_H
#define UART_H
/************************************************************************
Title: Interrupt UART library with receive/transmit circular buffers
Author: Peter Fleury <pfleury@gmx.ch> http://tinyurl.com/peterfleury
File: $Id: uart.h,v 1.13 2015/01/11 13:53:25 peter Exp $
Software: AVR-GCC 4.x, AVR Libc 1.4 or higher
Hardware: any AVR with built-in UART/USART
Usage: see Doxygen manual
LICENSE:
Copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
************************************************************************/
/**
* @file
* @defgroup pfleury_uart UART Library <uart.h>
* @code #include <uart.h> @endcode
*
* @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers.
*
* This library can be used to transmit and receive data through the built in UART.
*
* An interrupt is generated when the UART has finished transmitting or
* receiving a byte. The interrupt handling routines use circular buffers
* for buffering received and transmitted data.
*
* The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define
* the size of the circular buffers in bytes. Note that these constants must be a power of 2.
* You may need to adapt these constants to your target and your application by adding
* CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_TX_BUFFER_SIZE=nn to your Makefile.
*
* @note Based on Atmel Application Note AVR306
* @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury
* @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3
*/
#include <avr/pgmspace.h>
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405
#error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !"
#endif
/**@{*/
/*
** constants and macros
*/
/** @brief UART Baudrate Expression
* @param xtalCpu system clock in Mhz, e.g. 4000000UL for 4Mhz
* @param baudRate baudrate in bps, e.g. 1200, 2400, 9600
*/
#define UART_BAUD_SELECT(baudRate, xtalCpu) (((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) - 1UL)
/** @brief UART Baudrate Expression for ATmega double speed mode
* @param xtalCpu system clock in Mhz, e.g. 4000000UL for 4Mhz
* @param baudRate baudrate in bps, e.g. 1200, 2400, 9600
*/
#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate, xtalCpu) \
(((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) - 1UL)) | 0x8000)
/** @brief Size of the circular receive buffer, must be power of 2
*
* You may need to adapt this constant to your target and your application by adding
* CDEFS += -DUART_RX_BUFFER_SIZE=nn to your Makefile.
*/
#ifndef UART_RX_BUFFER_SIZE
#define UART_RX_BUFFER_SIZE 32
#endif
/** @brief Size of the circular transmit buffer, must be power of 2
*
* You may need to adapt this constant to your target and your application by adding
* CDEFS += -DUART_TX_BUFFER_SIZE=nn to your Makefile.
*/
#ifndef UART_TX_BUFFER_SIZE
#define UART_TX_BUFFER_SIZE 32
#endif
/* test if the size of the circular buffers fits into SRAM */
#if ((UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE) >= (RAMEND - 0x60))
#error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"
#endif
/*
** high byte error return code of uart_getc()
*/
#define UART_FRAME_ERROR 0x1000 /**< @brief Framing Error by UART */
#define UART_OVERRUN_ERROR 0x0800 /**< @brief Overrun condition by UART */
#define UART_PARITY_ERROR 0x0400 /**< @brief Parity Error by UART */
#define UART_BUFFER_OVERFLOW 0x0200 /**< @brief receive ringbuffer overflow */
#define UART_NO_DATA 0x0100 /**< @brief no receive data available */
/*
** function prototypes
*/
/**
@brief Initialize UART and set baudrate
@param baudrate Specify baudrate using macro UART_BAUD_SELECT()
@return none
*/
extern void uart_init(unsigned int baudrate);
/**
* @brief Get received byte from ringbuffer
*
* Returns in the lower byte the received character and in the
* higher byte the last receive error.
* UART_NO_DATA is returned when no data is available.
*
* @return lower byte: received byte from ringbuffer
* @return higher byte: last receive status
* - \b 0 successfully received data from UART
* - \b UART_NO_DATA
* <br>no receive data available
* - \b UART_BUFFER_OVERFLOW
* <br>Receive ringbuffer overflow.
* We are not reading the receive buffer fast enough,
* one or more received character have been dropped
* - \b UART_OVERRUN_ERROR
* <br>Overrun condition by UART.
* A character already present in the UART UDR register was
* not read by the interrupt handler before the next character arrived,
* one or more received characters have been dropped.
* - \b UART_FRAME_ERROR
* <br>Framing Error by UART
*/
extern unsigned int uart_getc(void);
/**
* @brief Put byte to ringbuffer for transmitting via UART
* @param data byte to be transmitted
* @return none
*/
extern void uart_putc(unsigned char data);
/**
* @brief Put string to ringbuffer for transmitting via UART
*
* The string is buffered by the uart library in a circular buffer
* and one character at a time is transmitted to the UART using interrupts.
* Blocks if it can not write the whole string into the circular buffer.
*
* @param s string to be transmitted
* @return none
*/
extern void uart_puts(const char *s);
/**
* @brief Put string from program memory to ringbuffer for transmitting via UART.
*
* The string is buffered by the uart library in a circular buffer
* and one character at a time is transmitted to the UART using interrupts.
* Blocks if it can not write the whole string into the circular buffer.
*
* @param s program memory string to be transmitted
* @return none
* @see uart_puts_P
*/
extern void uart_puts_p(const char *s);
/**
* @brief Macro to automatically put a string constant into program memory
*/
#define uart_puts_P(__s) uart_puts_p(PSTR(__s))
/** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */
extern void uart1_init(unsigned int baudrate);
/** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */
extern unsigned int uart1_getc(void);
/** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */
extern void uart1_putc(unsigned char data);
/** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */
extern void uart1_puts(const char *s);
/** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega)
* @see uart_puts_p */
extern void uart1_puts_p(const char *s);
/** @brief Macro to automatically put a string constant into program memory */
#define uart1_puts_P(__s) uart1_puts_p(PSTR(__s))
/**@}*/
#endif // UART_H

286
uart.hpp Normal file
View File

@@ -0,0 +1,286 @@
#pragma once
#include "config.hpp"
#include "hardware0.hpp"
#include "hardware1.hpp"
#include "software.hpp"
#include "../flash/flash.hpp"
#define FORCE_INLINE __attribute__((always_inline))
namespace uart {
namespace detail {
template <typename...>
struct always_false {
static constexpr auto value = false;
};
} // namespace detail
template <class Driver>
class Uart {
public:
// Initialization is done upon construction
Uart()
{
Driver::init();
}
// Moving and copying uart objects is not supported
Uart(const Uart &) = delete;
Uart(Uart &&) = delete;
Uart &operator=(const Uart &) = delete;
Uart &operator=(Uart &&) = delete;
static void txByte(const typename Driver::data_t &byte)
{
Driver::txByte(byte);
}
static bool rxByte(typename Driver::data_t &byte)
{
return Driver::rxByte(byte);
}
static bool peek(typename Driver::data_t &byte)
{
return Driver::peek(byte);
}
static bool peek()
{
return Driver::peek();
}
static void txString(const char *str)
{
static_assert(Driver::DATA_BITS == DataBits::EIGHT, "Strings are only supported with 8 data bits");
while (char ch = *str++)
txByte(ch);
}
static void txString(const ::detail::FlashString *str)
{
static_assert(Driver::DATA_BITS == DataBits::EIGHT, "Strings are only supported with 8 data bits");
const char *strIt = reinterpret_cast<const char *>(str);
while (char ch = pgm_read_byte(strIt++))
txByte(ch);
}
//////////////////////////////////////////////////////////////////////////
// Output stream overloads
Uart &operator<<(const char *str)
{
txString(str);
return *this;
}
Uart &operator<<(const ::detail::FlashString *str)
{
txString(str);
return *this;
}
template <typename... Ts>
Uart &operator<<(char)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(unsigned char)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(short)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(unsigned short)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(int)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(unsigned int)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(long)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(unsigned long)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(long long)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(unsigned long long)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(float)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(double)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(long double)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(bool)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator<<(const void *)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
//////////////////////////////////////////////////////////////////////////
// Input stream overloads
template <typename... Ts>
Uart &operator>>(char &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(unsigned char &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(short &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(unsigned short &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(int &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(unsigned int &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(long &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(unsigned long &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(long long &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(unsigned long long &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(float &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(double &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(long double &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(bool &)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
template <typename... Ts>
Uart &operator>>(const void *&)
{
static_assert(detail::always_false<Ts...>::value, "Not implemented");
}
};
template <typename cfg = Config<>>
using Uart0 = Uart<Hardware0<Mode::ASYNCHRONOUS, cfg>>;
#ifdef HAS_UART1
template <typename cfg = Config<>>
using Uart1 = Uart<Hardware1<Mode::ASYNCHRONOUS, cfg>>;
#endif
} // namespace uart
#undef FORCE_INLINE
#undef HAS_UART1

View File

@@ -1,22 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Atmel Studio Solution File, Format Version 11.00
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "usart", "usart\usart.cppproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|AVR = Debug|AVR
Release|AVR = Release|AVR
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.ActiveCfg = Debug|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.Build.0 = Debug|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.ActiveCfg = Release|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.Build.0 = Release|AVR
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -235,6 +235,66 @@ void USART0::setMode( Mode enmMode )
setUCSRC( ui8UCSRC ); setUCSRC( ui8UCSRC );
} }
//////////////////////////////////////////////////////////////////////////
uint32_t USART0::getBaudRate()
{
uint16_t ui16UBRR;
ui16UBRR = static_cast<uint16_t>( *m_vui8pUBRRH ) << 8;
ui16UBRR |= *m_vui8pUBRRL;
return F_CPU / ( static_cast<uint32_t>( 16 ) * ( ui16UBRR + 1 ) );
}
//////////////////////////////////////////////////////////////////////////
uint8_t USART0::getDataBits()
{
if( *m_vui8pUCSRB & ( 1 << UCSZ2_D ) )
{
return 9;
}
uint8_t ui8UCSRC = readUCSRC();
bool bZeroBit = ui8UCSRC & ( 1 << UCSZ0_D );
bool bOneBit = ui8UCSRC & ( 1 << UCSZ1_D );
return 5 + ( bOneBit << 1 | bZeroBit );
}
//////////////////////////////////////////////////////////////////////////
USART0::Parity USART0::getParity()
{
uint8_t ui8UCSRC = readUCSRC();
bool bZeroBit = ui8UCSRC & ( 1 << UPM0_D );
bool bOneBit = ui8UCSRC & ( 1 << UPM1_D );
if( bOneBit && !bZeroBit )
{
return Parity::EVEN;
}
if( bOneBit && bZeroBit )
{
return Parity::ODD;
}
return Parity::DISABLED;
}
//////////////////////////////////////////////////////////////////////////
USART0::StopBit USART0::getStopBits()
{
uint8_t ui8UCSRC = readUCSRC();
if( ui8UCSRC & ( 1 << USBS_D ) )
{
return StopBit::TWO;
}
return StopBit::ONE;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
USART0::~USART0() USART0::~USART0()
{ {
@@ -300,7 +360,7 @@ bool USART0::receiveByte( uint8_t &ui8Data, uint16_t ui16TimeoutMS )
{ {
_delay_ms( 1 ); _delay_ms( 1 );
if( ui16DelayCounter++ >= ui16TimeoutMS ) if( ui16DelayCounter++ > ui16TimeoutMS )
{ {
return false; return false;
} }
@@ -309,6 +369,39 @@ bool USART0::receiveByte( uint8_t &ui8Data, uint16_t ui16TimeoutMS )
return true; return true;
} }
//////////////////////////////////////////////////////////////////////////
uint8_t USART0::receiveByteBlocked()
{
uint8_t ui8Received;
while( !receiveByte( ui8Received ) );
return ui8Received;
}
//////////////////////////////////////////////////////////////////////////
uint8_t USART0::receivePeek()
{
uint8_t ui8Received;
if( !( SREG & ( 1 << SREG_I ) && m_vsizeRXBufferHead == m_vsizeRXBufferTail ) )
{
while( !( *m_vui8pUCSRA & ( 1 << RXC_D ) ) );
ui8Received = *m_vui8pUDR;
size_t sizeIndex = ( m_vsizeRXBufferHead + 1 ) % sm_sizeRXBUFFER_SIZE;
if( sizeIndex != m_vsizeRXBufferTail )
{
m_vui8aRXBuffer[m_vsizeRXBufferHead] = ui8Received;
m_vsizeRXBufferHead = sizeIndex;
}
return ui8Received;
}
while( m_vsizeRXBufferHead == m_vsizeRXBufferTail );
return m_vui8aRXBuffer[m_vsizeRXBufferTail];
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, const char *szLineTerminator /* = "\r\n" */ ) bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, const char *szLineTerminator /* = "\r\n" */ )
{ {
@@ -324,6 +417,41 @@ bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, const char *s
if( strstr( szBuffer, szLineTerminator ) ) if( strstr( szBuffer, szLineTerminator ) )
{ {
szBuffer[sizeReceived - strlen( szLineTerminator )] = '\0';
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////
bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, uint16_t ui16TimeoutMS, const char *szLineTerminator /* = "\r\n" */ )
{
size_t sizeReceived = 0;
while( sizeReceived < sizeBufferLength - 1 )
{
uint8_t ui8ReceiveByte;
uint16_t ui16DelayCounter = 0;
while( !receiveByte( ui8ReceiveByte ) )
{
_delay_ms( 1 );
if( ui16DelayCounter++ > ui16TimeoutMS )
{
szBuffer[sizeReceived] = '\0';
return false;
}
}
szBuffer[sizeReceived++] = ui8ReceiveByte;
szBuffer[sizeReceived] = '\0';
if( strstr( szBuffer, szLineTerminator ) )
{
szBuffer[sizeReceived - strlen( szLineTerminator )] = '\0';
return true; return true;
} }
} }
@@ -334,16 +462,56 @@ bool USART0::receiveLine( char *szBuffer, size_t sizeBufferLength, const char *s
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void USART0::flushReceive() void USART0::flushReceive()
{ {
uint8_t ui8Received; uint32_t ui32BaudRate = getBaudRate();
uint8_t ui8BitsPerSymbol = 1;
while( m_vsizeRXBufferHead != m_vsizeRXBufferTail ) ui8BitsPerSymbol += getDataBits();
if( getParity() != Parity::DISABLED )
{ {
receiveByte( ui8Received ); ui8BitsPerSymbol += 1;
} }
if( !( SREG & ( 1 << SREG_I ) ) && ( *m_vui8pUCSRA & ( 1 << RXC_D ) ) ) if( getStopBits() == StopBit::ONE )
{ {
ui8Received = *m_vui8pUDR; ui8BitsPerSymbol += 1;
}
else
{
ui8BitsPerSymbol += 2;
}
uint16_t ui16BaudDelayMS = static_cast<uint16_t>( ( 1000.0 * ui8BitsPerSymbol ) / ui32BaudRate ) + 1;
uint8_t ui8Received;
if( !( SREG & ( 1 << SREG_I ) ) )
{
while( true )
{
for( uint16_t i = 0; i < ui16BaudDelayMS; ++i )
{
_delay_ms( 1 );
}
if( m_vsizeRXBufferHead != m_vsizeRXBufferTail )
{
receiveByte( ui8Received );
continue;
}
if( ( *m_vui8pUCSRA & ( 1 << RXC_D ) ) )
{
ui8Received = *m_vui8pUDR;
continue;
}
break;
}
}
else
{
while( receiveByte( ui8Received, ui16BaudDelayMS ) );
} }
} }

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (c) by BlackMark 2015-2016 * Copyright (c) by BlackMark 2015-2018
* Date 24/05/2016 * Date 12/04/2018
* Version 2.9 * Version 3.4
*/ */
#ifndef USART_H #ifndef USART_H
@@ -11,19 +11,20 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "clock.h" #include "../clock.h"
#if defined (__AVR_ATmega168A__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega1284P__) #if defined (__AVR_ATmega168A__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega644P__)
#define USART_SPI #define USART_SPI
#define USART0_RX_vect_D USART_RX_vect #define USART0_RX_vect_D USART_RX_vect
#define USART0_UDRE_vect_D USART_UDRE_vect #define USART0_UDRE_vect_D USART_UDRE_vect
#endif #endif
#if defined (__AVR_ATmega32A__) || (__AVR_ATmega8__) #if defined (__AVR_ATmega32A__) || (__AVR_ATmega8__) || (__AVR_ATmega8A__)
#define USART_SHAREDIO #define USART_SHAREDIO
#define USART0_RX_vect_D USART_RXC_vect #define USART0_RX_vect_D USART_RXC_vect
#define USART0_UDRE_vect_D USART_UDRE_vect #define USART0_UDRE_vect_D USART_UDRE_vect
#endif #endif
#if defined (__AVR_ATmega1284P__) #if defined (__AVR_ATmega1284P__)
#define USART_SPI
#define SECOND_USART #define SECOND_USART
#define USART0_RX_vect_D USART0_RX_vect #define USART0_RX_vect_D USART0_RX_vect
#define USART1_RX_vect_D USART1_RX_vect #define USART1_RX_vect_D USART1_RX_vect
@@ -128,9 +129,14 @@ private:
void setStopBits( StopBit enmStopBits ); void setStopBits( StopBit enmStopBits );
void setMode( Mode enmMode ); void setMode( Mode enmMode );
~USART0(); uint32_t getBaudRate();
uint8_t getDataBits();
Parity getParity();
StopBit getStopBits();
public: public:
~USART0();
static USART0& inst(); static USART0& inst();
USART0( const USART0& ) = delete; USART0( const USART0& ) = delete;
void operator=( const USART0& ) = delete; void operator=( const USART0& ) = delete;
@@ -139,7 +145,10 @@ public:
bool receiveByte( uint8_t &ui8Data ); bool receiveByte( uint8_t &ui8Data );
bool receiveByte( uint8_t &ui8Data, uint16_t ui16TimeoutMS ); bool receiveByte( uint8_t &ui8Data, uint16_t ui16TimeoutMS );
uint8_t receiveByteBlocked();
uint8_t receivePeek();
bool receiveLine( char *szBuffer, size_t sizeBufferLength, const char *szLineTerminator = "\r\n" ); bool receiveLine( char *szBuffer, size_t sizeBufferLength, const char *szLineTerminator = "\r\n" );
bool receiveLine( char *szBuffer, size_t sizeBufferLength, uint16_t ui16TimeoutMS, const char *szLineTerminator = "\r\n" );
void flushReceive(); void flushReceive();
void transmitByte( uint8_t ui8Data ); void transmitByte( uint8_t ui8Data );

Submodule usart/array deleted from 634564a7bb

View File

@@ -1,14 +0,0 @@
/*
* Copyright (c) by BlackMark 2015
* Date 24/11/2015
* Version 1.1
*/
#ifndef CLOCK_H
#define CLOCK_H
#define F_CPU 8000000
#include <util/delay.h>
#endif

View File

@@ -1,92 +0,0 @@
/*
* Copyright (c) by BlackMark 2015-2016
* Date 21/05/2016
* Version 1.5
*/
#include <stdio.h>
#include "clock.h"
#include "usart.h"
#include "array/array.h"
int main()
{
sei();
USART0 &cUSART = USART0::inst();
cUSART.init();
uint32_t ui32Counter = 0;
array<char, 64> arrBuffer;
cUSART << "\r\nSizes: \r\n";
sprintf( arrBuffer.data(), "%d\r\n", sizeof( char ) );
cUSART << "sizeof( char ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( unsigned char ) );
cUSART << "sizeof( unsigned char ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( short int ) );
cUSART << "sizeof( short int ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( unsigned short int ) );
cUSART << "sizeof( unsigned short int ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( int ) );
cUSART << "sizeof( int ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( unsigned int ) );
cUSART << "sizeof( unsigned int ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( long int ) );
cUSART << "sizeof( long int ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( unsigned long int ) );
cUSART << "sizeof( unsigned long int ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( long long int ) );
cUSART << "sizeof( long long int ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( unsigned long long int ) );
cUSART << "sizeof( unsigned long long int ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( float ) );
cUSART << "sizeof( float ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( double ) );
cUSART << "sizeof( double ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n", sizeof( long double ) );
cUSART << "sizeof( long double ) = " << arrBuffer.data();
sprintf( arrBuffer.data(), "%d\r\n\r\n", sizeof( void* ) );
cUSART << "sizeof( void* ) = " << arrBuffer.data();
while( true )
{
sprintf( arrBuffer.data(), "%lu", ui32Counter++ );
cUSART << "This has been running for \"" << arrBuffer.data() << "\" seconds!\r\n";
if( !cUSART.receiveLine( arrBuffer.data(), arrBuffer.size(), "\r" ) )
{
cUSART << "Receive error: ";
}
else
{
cUSART << "Echo: ";
}
cUSART << arrBuffer.data() << "\r\n";
uint8_t ui8Byte;
if( cUSART.receiveByte( ui8Byte, 1000 ) )
{
cUSART.transmitByte( ui8Byte );
cUSART << "\r\n";
}
}
return 0;
}

View File

@@ -1,215 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>7.0</ProjectVersion>
<ToolchainName>com.Atmel.AVRGCC8.CPP</ToolchainName>
<ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
<avrdevice>ATmega328P</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>Executable</OutputType>
<Language>CPP</Language>
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<AssemblyName>usart</AssemblyName>
<Name>usart</Name>
<RootNamespace>usart</RootNamespace>
<ToolchainFlavour>Native</ToolchainFlavour>
<KeepTimersRunning>true</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>true</CacheFlash>
<ProgFlashFromRam>true</ProgFlashFromRam>
<RamSnippetAddress>0x20000000</RamSnippetAddress>
<UncachedRange />
<preserveEEPROM>true</preserveEEPROM>
<OverrideVtorValue>exception_table</OverrideVtorValue>
<BootSegment>2</BootSegment>
<eraseonlaunchrule>0</eraseonlaunchrule>
<AsfFrameworkConfig>
<framework-data xmlns="">
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.31.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
<avrtool>com.atmel.avrdbg.tool.stk500</avrtool>
<avrtoolserialnumber />
<avrdeviceexpectedsignature>0x1E950F</avrdeviceexpectedsignature>
<com_atmel_avrdbg_tool_stk500>
<ToolOptions>
<InterfaceProperties>
<IspClock>1843200</IspClock>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.stk500</ToolType>
<ToolNumber>
</ToolNumber>
<ToolName>STK500</ToolName>
</com_atmel_avrdbg_tool_stk500>
<avrtoolinterface>ISP</avrtoolinterface>
<avrtoolinterfaceclock>1843200</avrtoolinterfaceclock>
<com_atmel_avrdbg_tool_simulator>
<ToolOptions xmlns="">
<InterfaceProperties>
</InterfaceProperties>
<InterfaceName>
</InterfaceName>
</ToolOptions>
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
<ToolNumber xmlns="">
</ToolNumber>
<ToolName xmlns="">Simulator</ToolName>
</com_atmel_avrdbg_tool_simulator>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.0.106\gcc\dev\atmega328p"</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.0.106\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.0.106\include</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-Wextra -std=c++11</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.general.UseVprintfLibrary>True</avrgcccpp.linker.general.UseVprintfLibrary>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
<Value>libprintf_flt</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.0.106\include</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
</AvrGccCpp>
</ToolchainSettings>
<PreBuildEvent>echo "C:\avrdude-6.2\avrdude.exe" -v -p$(avrdevice) %%* -Uflash:w:"$(OutputDirectory)\$(Name).hex":i &gt; "$(MSBuildProjectDirectory)\avrdude.bat"</PreBuildEvent>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=atmega328p -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.0.106\gcc\dev\atmega328p"</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.0.106\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.0.106\include</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.compiler.warnings.Pedantic>True</avrgcccpp.compiler.warnings.Pedantic>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-Wextra -std=c++11</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.general.UseVprintfLibrary>True</avrgcccpp.linker.general.UseVprintfLibrary>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
<Value>libprintf_flt</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.0.106\include</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.optimization.level>Optimize (-O1)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.DebugLevel>Default (-g2)</avrgcccpp.compiler.optimization.DebugLevel>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp>
</ToolchainSettings>
<PreBuildEvent>echo "C:\avrdude-6.2\avrdude.exe" -v -p$(avrdevice) %%* -Uflash:w:"$(OutputDirectory)\$(Name).hex":i &gt; "$(MSBuildProjectDirectory)\avrdude.bat"</PreBuildEvent>
</PropertyGroup>
<ItemGroup>
<Compile Include="array\array.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="clock.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="main.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="usart.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="usart.h">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="array" />
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>