From bdf4bd169ebd44c89860b753c0912498b348a9cd Mon Sep 17 00:00:00 2001 From: BlackMark Date: Fri, 2 Aug 2019 09:21:47 +0200 Subject: [PATCH] Moved hardware abstraction to separate header --- hardware.hpp | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++ hardware0.hpp | 143 +-------------------------------------------- hardware1.hpp | 2 +- 3 files changed, 159 insertions(+), 143 deletions(-) create mode 100644 hardware.hpp diff --git a/hardware.hpp b/hardware.hpp new file mode 100644 index 0000000..aa352e7 --- /dev/null +++ b/hardware.hpp @@ -0,0 +1,157 @@ +#pragma once + +#include "config.hpp" + +#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 Hardware { + public: + static void init() FORCE_INLINE + { + constexpr auto baudVal = calcBaud(); + + *Registers::BAUD_REG_H = static_cast(baudVal >> 8); + *Registers::BAUD_REG_L = static_cast(baudVal); + + constexpr auto dataBitsVal = calcDataBits(); + constexpr auto parityVal = calcParity(); + constexpr auto stopBitsVal = calcStopBits(); + constexpr auto modeVal = calcMode(); + constexpr auto enableRx = calcRxState(); + constexpr auto enableTx = calcTxState(); + + constexpr uint8_t controlRegB = dataBitsVal.regBVal | enableRx | enableTx; + constexpr uint8_t controlRegC = dataBitsVal.regCVal | parityVal | stopBitsVal | modeVal; + + *Registers::CTRL_STAT_REG_B = controlRegB; + *Registers::CTRL_STAT_REG_C = controlRegC; + } + + static void txByte(typename cfg::data_t byte) FORCE_INLINE + { + while (!(*Registers::CTRL_STAT_REG_A & (1 << CtrlFlagsA::DATA_REG_EMPTY))) + ; + + *Registers::IO_REG = byte; + } + + 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 + static constexpr auto calcRxState() + { + uint8_t enableVal = 0; + + if (enable) + enableVal = (1 << CtrlFlagsB::RX_ENABLE); + + return enableVal; + } + + template + static constexpr auto calcTxState() + { + uint8_t enableVal = 0; + + if (enable) + enableVal = (1 << CtrlFlagsB::TX_ENABLE); + + return enableVal; + } +}; + +} // namespace detail + +} // namespace uart + +#undef FORCE_INLINE diff --git a/hardware0.hpp b/hardware0.hpp index 1f4820e..b06cae4 100644 --- a/hardware0.hpp +++ b/hardware0.hpp @@ -1,24 +1,12 @@ #pragma once #include "config.hpp" +#include "hardware.hpp" #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 { #if defined(__AVR_ATmega1284P__) @@ -75,135 +63,6 @@ constexpr int operator<<(const int &lhs, const ControlFlagsC0 &rhs) { return lhs #error "This chip is not supported" #endif -template -class Hardware { - public: - static void init() FORCE_INLINE - { - constexpr auto baudVal = calcBaud(); - - *Registers::BAUD_REG_H = static_cast(baudVal >> 8); - *Registers::BAUD_REG_L = static_cast(baudVal); - - constexpr auto dataBitsVal = calcDataBits(); - constexpr auto parityVal = calcParity(); - constexpr auto stopBitsVal = calcStopBits(); - constexpr auto modeVal = calcMode(); - constexpr auto enableRx = calcRxState(); - constexpr auto enableTx = calcTxState(); - - constexpr uint8_t controlRegB = dataBitsVal.regBVal | enableRx | enableTx; - constexpr uint8_t controlRegC = dataBitsVal.regCVal | parityVal | stopBitsVal | modeVal; - - *Registers::CTRL_STAT_REG_B = controlRegB; - *Registers::CTRL_STAT_REG_C = controlRegC; - } - - static void txByte(typename cfg::data_t byte) FORCE_INLINE - { - while (!(*Registers::CTRL_STAT_REG_A & (1 << CtrlFlagsA::DATA_REG_EMPTY))) - ; - - *Registers::IO_REG = byte; - } - - 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 - static constexpr auto calcRxState() - { - uint8_t enableVal = 0; - - if (enable) - enableVal = (1 << CtrlFlagsB::RX_ENABLE); - - return enableVal; - } - - template - static constexpr auto calcTxState() - { - uint8_t enableVal = 0; - - if (enable) - enableVal = (1 << CtrlFlagsB::TX_ENABLE); - - return enableVal; - } -}; - } // namespace detail template , Driven driven = Driven::INTERRUPT> diff --git a/hardware1.hpp b/hardware1.hpp index 66b0379..9addb16 100644 --- a/hardware1.hpp +++ b/hardware1.hpp @@ -1,6 +1,6 @@ #pragma once -#include "hardware0.hpp" +#include "hardware.hpp" #define FORCE_INLINE __attribute__((always_inline))