// Copyright 2011 Olivier Gillet.
//
// Author: Olivier Gillet (ol.gillet@gmail.com)
//
// 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
// (at your option) 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.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
#ifndef AVRLIBX_IO_USART_H_
#define AVRLIBX_IO_USART_H_
#include
#include "avrlibx/avrlibx.h"
namespace avrlibx {
enum RxMode {
RX_DISABLED,
RX_POLLED
};
enum TxMode {
TX_DISABLED,
TX_POLLED
};
template struct USARTWrapper { };
#define WRAP_USART(port, index) \
template<> \
struct USARTWrapper { \
static inline USART_t& usart() { \
return USART ## port ## index; \
} \
static volatile inline uint8_t data() { \
return USART ## port ## index ## _DATA; \
} \
static inline void set_data(uint16_t value) { \
USART ## port ## index ## _DATA = value; \
} \
static inline uint8_t readable() { \
return USART ## port ## index ## _STATUS & USART_RXCIF_bm; \
} \
static inline uint8_t writable_buffer() { \
return USART ## port ## index ## _STATUS & USART_DREIF_bm; \
} \
static inline uint8_t writable() { \
return USART ## port ## index ## _STATUS & USART_TXCIF_bm; \
} \
static inline uint8_t dma_rx_trigger() { \
return DMA_CH_TRIGSRC_USART ## port ## index ## _RXC_gc; \
} \
static inline uint8_t dma_tx_trigger() { \
return DMA_CH_TRIGSRC_USART ## port ## index ## _DRE_gc; \
} \
static inline volatile void* dma_data() { \
return &(USART ## port ## index ## _DATA); \
} \
};
WRAP_USART(C, 0)
WRAP_USART(C, 1)
WRAP_USART(D, 0)
WRAP_USART(D, 1)
WRAP_USART(E, 0)
#ifdef USARTE1
WRAP_USART(E, 1)
#endif
#ifdef USARTF0
WRAP_USART(F, 0)
#endif
#ifdef USARTF1
WRAP_USART(F, 1)
#endif
template<
typename Port,
uint8_t index,
uint32_t baud_rate,
RxMode rx_mode,
TxMode tx_mode>
struct Usart {
typedef USARTWrapper USART;
static inline void Init() {
Init();
}
template
static inline void Init() {
uint16_t prescaler = F_CPU / (16 * baud_rate) - 1;
USART::usart().BAUDCTRLA = prescaler & 0xff;
USART::usart().BAUDCTRLB = (prescaler >> 8) & 0xf;
uint8_t control;
if (rx_mode != RX_DISABLED) {
control |= USART_RXEN_bm;
}
if (tx_mode != TX_DISABLED) {
if (index == 0) {
Gpio::set_direction(OUTPUT);
} else {
Gpio::set_direction(OUTPUT);
}
control |= USART_TXEN_bm;
}
USART::usart().CTRLB = control;
}
static inline void Write(uint8_t v) { while (!writable()); Overwrite(v); }
static inline uint8_t writable() { return USART::writable_buffer(); }
static inline uint8_t NonBlockingWrite(uint8_t v) {
if (!writable()) {
return 0;
}
Overwrite(v);
return 1;
}
static inline void Overwrite(uint8_t v) { USART::set_data(v); }
static inline uint8_t Read() { while (!readable()); return ImmediateRead(); }
static inline uint8_t readable() { return USART::readable(); }
static inline uint16_t NonBlockingRead() {
return readable() ? ImmediateRead() : -1;
}
static inline uint8_t ImmediateRead() { return USART::data(); }
static inline uint8_t dma_rx_trigger() {
return USART::dma_rx_trigger();
}
static inline uint8_t dma_tx_trigger() {
return USART::dma_rx_trigger();
}
static inline volatile void* dma_data() {
return USART::dma_data();
}
typedef uint8_t Value;
};
} // namespace avrlibx
#endif // AVRLIBX_IO_USART_H_