Implemented basic hardware support for transmitting
This commit is contained in:
parent
a71035d4b7
commit
8e0ba5a463
198
hardware0.hpp
198
hardware0.hpp
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
|
#define FORCE_INLINE __attribute__((always_inline))
|
||||||
|
|
||||||
namespace uart {
|
namespace uart {
|
||||||
|
|
||||||
enum class Mode {
|
enum class Mode {
|
||||||
@ -17,17 +19,203 @@ enum class Driven {
|
|||||||
BLOCKING,
|
BLOCKING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
struct Registers0 {
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SupportedHardware {
|
||||||
|
ATmega1284P,
|
||||||
|
};
|
||||||
|
|
||||||
|
template <SupportedHardware>
|
||||||
|
struct HardwareAbstraction {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct HardwareAbstraction<SupportedHardware::ATmega1284P> {
|
||||||
|
struct Reg0 {
|
||||||
|
static constexpr volatile auto *ioReg = &UDR0;
|
||||||
|
static constexpr volatile auto *controlStatusRegA = &UCSR0A;
|
||||||
|
static constexpr volatile auto *controlStatusRegB = &UCSR0B;
|
||||||
|
static constexpr volatile auto *controlStatusRegC = &UCSR0C;
|
||||||
|
static constexpr volatile auto *baudRateRegL = &UBRR0L;
|
||||||
|
static constexpr volatile auto *baudRateRegH = &UBRR0H;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Reg1 {
|
||||||
|
static constexpr volatile auto *ioReg = &UDR1;
|
||||||
|
static constexpr volatile auto *controlStatusRegA = &UCSR1A;
|
||||||
|
static constexpr volatile auto *controlStatusRegB = &UCSR1B;
|
||||||
|
static constexpr volatile auto *controlStatusRegC = &UCSR1C;
|
||||||
|
static constexpr volatile auto *baudRateRegL = &UBRR1L;
|
||||||
|
static constexpr volatile auto *baudRateRegH = &UBRR1H;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <uint32_t baudRate>
|
||||||
|
static constexpr auto calcBaud()
|
||||||
|
{
|
||||||
|
return static_cast<uint16_t>((F_CPU / (16 * baudRate)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DataBitsVal {
|
||||||
|
uint8_t ucsrcVal = 0;
|
||||||
|
uint8_t ucsrbVal = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <DataBits dataBits>
|
||||||
|
static constexpr auto calcDataBits()
|
||||||
|
{
|
||||||
|
DataBitsVal dataBitsVal;
|
||||||
|
|
||||||
|
switch (dataBits) {
|
||||||
|
case DataBits::FIVE:
|
||||||
|
dataBitsVal.ucsrcVal = 0;
|
||||||
|
break;
|
||||||
|
case DataBits::SIX:
|
||||||
|
dataBitsVal.ucsrcVal = (1 << UCSZ00);
|
||||||
|
break;
|
||||||
|
case DataBits::SEVEN:
|
||||||
|
dataBitsVal.ucsrcVal = (1 << UCSZ01);
|
||||||
|
break;
|
||||||
|
case DataBits::EIGHT:
|
||||||
|
dataBitsVal.ucsrcVal = (1 << UCSZ01) | (1 << UCSZ00);
|
||||||
|
break;
|
||||||
|
case DataBits::NINE:
|
||||||
|
dataBitsVal.ucsrcVal = (1 << UCSZ01) | (1 << UCSZ00);
|
||||||
|
dataBitsVal.ucsrbVal = (1 << UCSZ02);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataBitsVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Parity parity>
|
||||||
|
static constexpr auto calcParity()
|
||||||
|
{
|
||||||
|
uint8_t parityVal = 0;
|
||||||
|
|
||||||
|
if (parity == Parity::EVEN)
|
||||||
|
parityVal = (1 << UPM01);
|
||||||
|
else if (parity == Parity::ODD)
|
||||||
|
parityVal = (1 << UPM01) | (1 << UPM00);
|
||||||
|
|
||||||
|
return parityVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <StopBits stopBits>
|
||||||
|
static constexpr auto calcStopBits()
|
||||||
|
{
|
||||||
|
uint8_t stopBitsVal = 0;
|
||||||
|
|
||||||
|
if (stopBits == StopBits::TWO)
|
||||||
|
stopBitsVal = (1 << USBS0);
|
||||||
|
|
||||||
|
return stopBitsVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Mode mode>
|
||||||
|
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 << UMSEL00);
|
||||||
|
}
|
||||||
|
|
||||||
|
return modeVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool enable>
|
||||||
|
static constexpr auto calcRxState()
|
||||||
|
{
|
||||||
|
uint8_t enableVal = 0;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
enableVal = (1 << RXEN0);
|
||||||
|
|
||||||
|
return enableVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool enable>
|
||||||
|
static constexpr auto calcTxState()
|
||||||
|
{
|
||||||
|
uint8_t enableVal = 0;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
enableVal = (1 << TXEN0);
|
||||||
|
|
||||||
|
return enableVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setBaud(const uint16_t baudVal)
|
||||||
|
{
|
||||||
|
*Reg0::baudRateRegH = static_cast<uint8_t>(baudVal >> 8);
|
||||||
|
*Reg0::baudRateRegL = static_cast<uint8_t>(baudVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <uint8_t regVal>
|
||||||
|
static void setControlRegA()
|
||||||
|
{
|
||||||
|
*Reg0::controlStatusRegA = regVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <uint8_t regVal>
|
||||||
|
static void setControlRegB()
|
||||||
|
{
|
||||||
|
*Reg0::controlStatusRegB = regVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <uint8_t regVal>
|
||||||
|
static void setControlRegC()
|
||||||
|
{
|
||||||
|
*Reg0::controlStatusRegC = regVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void txByte(uint8_t byte) FORCE_INLINE
|
||||||
|
{
|
||||||
|
while (!(*Reg0::controlStatusRegA & (1 << UDRE0)))
|
||||||
|
;
|
||||||
|
|
||||||
|
*Reg0::ioReg = byte;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr auto currentHardware = SupportedHardware::ATmega1284P;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
template <Mode mode = Mode::ASYNCHRONOUS, class cfg = config<>, Driven driven = Driven::INTERRUPT>
|
template <Mode mode = Mode::ASYNCHRONOUS, class cfg = config<>, Driven driven = Driven::INTERRUPT>
|
||||||
class hardware0 {
|
class hardware0 {
|
||||||
public:
|
public:
|
||||||
using data_t = typename cfg::data_t;
|
using data_t = typename cfg::data_t;
|
||||||
static constexpr auto DATA_BITS = cfg::DATA_BITS;
|
static constexpr auto DATA_BITS = cfg::DATA_BITS;
|
||||||
|
|
||||||
static void init() {}
|
static void init()
|
||||||
|
|
||||||
static void txByte(data_t byte)
|
|
||||||
{
|
{
|
||||||
static_cast<void>(byte);
|
detail::HardwareAbstraction<detail::currentHardware> hal;
|
||||||
|
hal.setBaud(hal.calcBaud<BAUD_RATE>());
|
||||||
|
|
||||||
|
constexpr auto dataBitsVal = hal.calcDataBits<DATA_BITS>();
|
||||||
|
constexpr auto parityVal = hal.calcParity<PARITY>();
|
||||||
|
constexpr auto stopBitsVal = hal.calcStopBits<STOP_BITS>();
|
||||||
|
constexpr auto modeVal = hal.calcMode<mode>();
|
||||||
|
constexpr auto enableRx = hal.calcRxState<true>();
|
||||||
|
constexpr auto enableTx = hal.calcTxState<true>();
|
||||||
|
|
||||||
|
constexpr uint8_t ucsr0b = dataBitsVal.ucsrbVal | enableRx | enableTx;
|
||||||
|
constexpr uint8_t ucsr0c = dataBitsVal.ucsrcVal | parityVal | stopBitsVal | modeVal;
|
||||||
|
|
||||||
|
hal.setControlRegB<ucsr0b>();
|
||||||
|
hal.setControlRegC<ucsr0c>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void txByte(data_t byte) FORCE_INLINE
|
||||||
|
{
|
||||||
|
detail::HardwareAbstraction<detail::currentHardware> hal;
|
||||||
|
hal.txByte(byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
static data_t rxByte() {}
|
static data_t rxByte() {}
|
||||||
@ -41,3 +229,5 @@ class hardware0 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace uart
|
} // namespace uart
|
||||||
|
|
||||||
|
#undef FORCE_INLINE
|
||||||
|
14
uart.hpp
14
uart.hpp
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "../flash/flash.hpp"
|
#include "../flash/flash.hpp"
|
||||||
|
|
||||||
|
#define FORCE_INLINE __attribute__((always_inline))
|
||||||
|
|
||||||
namespace uart {
|
namespace uart {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -33,7 +35,7 @@ class uart {
|
|||||||
uart &operator=(const uart &) = delete;
|
uart &operator=(const uart &) = delete;
|
||||||
uart &operator=(uart &&) = delete;
|
uart &operator=(uart &&) = delete;
|
||||||
|
|
||||||
static void txByte(typename Driver::data_t byte)
|
static void txByte(typename Driver::data_t byte) FORCE_INLINE
|
||||||
{
|
{
|
||||||
Driver::txByte(byte);
|
Driver::txByte(byte);
|
||||||
}
|
}
|
||||||
@ -48,7 +50,7 @@ class uart {
|
|||||||
return Driver::peek();
|
return Driver::peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void txString(const char *str)
|
static void txString(const char *str) FORCE_INLINE
|
||||||
{
|
{
|
||||||
static_assert(Driver::DATA_BITS == DataBits::EIGHT, "Strings are only supported with 8 data bits");
|
static_assert(Driver::DATA_BITS == DataBits::EIGHT, "Strings are only supported with 8 data bits");
|
||||||
|
|
||||||
@ -56,7 +58,7 @@ class uart {
|
|||||||
txByte(ch);
|
txByte(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void txString(const ::detail::FlashString *str)
|
static void txString(const ::detail::FlashString *str) FORCE_INLINE
|
||||||
{
|
{
|
||||||
static_assert(Driver::DATA_BITS == DataBits::EIGHT, "Strings are only supported with 8 data bits");
|
static_assert(Driver::DATA_BITS == DataBits::EIGHT, "Strings are only supported with 8 data bits");
|
||||||
|
|
||||||
@ -69,13 +71,13 @@ class uart {
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// Output stream overloads
|
// Output stream overloads
|
||||||
|
|
||||||
uart &operator<<(const char *str)
|
uart &operator<<(const char *str) FORCE_INLINE
|
||||||
{
|
{
|
||||||
txString(str);
|
txString(str);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
uart &operator<<(const ::detail::FlashString *str)
|
uart &operator<<(const ::detail::FlashString *str) FORCE_INLINE
|
||||||
{
|
{
|
||||||
txString(str);
|
txString(str);
|
||||||
return *this;
|
return *this;
|
||||||
@ -266,3 +268,5 @@ class uart {
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace uart
|
} // namespace uart
|
||||||
|
|
||||||
|
#undef FORCE_INLINE
|
||||||
|
Loading…
Reference in New Issue
Block a user