From 65bbf5e96aae9be573efef59a6e41f74a6d5f54b Mon Sep 17 00:00:00 2001 From: BlackMark Date: Tue, 30 Jul 2019 20:29:38 +0200 Subject: [PATCH] Refactored hardware abstraction --- hardware0.hpp | 200 +++++++++++++++++++++----------------------------- 1 file changed, 82 insertions(+), 118 deletions(-) diff --git a/hardware0.hpp b/hardware0.hpp index 9b88355..7f352c9 100644 --- a/hardware0.hpp +++ b/hardware0.hpp @@ -21,99 +21,140 @@ enum class Driven { namespace detail { -enum class SupportedHardware { - ATmega1284P, +#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; }; -template -struct HardwareAbstraction { -}; +static constexpr auto getLastRxError() {} +static constexpr void set2xSpeed() {} -template <> -struct HardwareAbstraction { - 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; - }; +template +static inline void setBaudRate() +{ + *Registers0::BAUD_REG_H = static_cast(BaudVal >> 8); + *Registers0::BAUD_REG_L = static_cast(BaudVal); +} - 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 +static inline void setCtrlStatRegC() +{ + *Registers0::CTRL_STAT_REG_C = RegVal; +} + +#else +#error "This chip is not supported" +#endif + +} // namespace detail + +template , 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() + { + detail::setBaudRate(); + + 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; + + *detail::Registers0::CTRL_STAT_REG_B = controlRegB; + detail::setCtrlStatRegC(); + } + + static void txByte(data_t byte) FORCE_INLINE + { + while (!(*detail::Registers0::CTRL_STAT_REG_A & (1 << UDRE0))) + ; + + *detail::Registers0::IO_REG = byte; + } + + static data_t rxByte() {} + + static data_t peek() {} + + private: + static constexpr auto BAUD_RATE = cfg::BAUD_RATE; + static constexpr auto PARITY = cfg::PARITY; + static constexpr auto STOP_BITS = cfg::STOP_BITS; - template 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 * baudRate) / (16 * baudRate) - 1; + constexpr auto baudVal = (F_CPU + 8 * BAUD_RATE) / (16 * BAUD_RATE) - 1; return baudVal; } struct DataBitsVal { - uint8_t ucsrcVal = 0; - uint8_t ucsrbVal = 0; + uint8_t regCVal = 0; + uint8_t regBVal = 0; }; - template static constexpr auto calcDataBits() { DataBitsVal dataBitsVal; - switch (dataBits) { + switch (DATA_BITS) { case DataBits::FIVE: - dataBitsVal.ucsrcVal = 0; + dataBitsVal.regCVal = 0; break; case DataBits::SIX: - dataBitsVal.ucsrcVal = (1 << UCSZ00); + dataBitsVal.regCVal = (1 << UCSZ00); break; case DataBits::SEVEN: - dataBitsVal.ucsrcVal = (1 << UCSZ01); + dataBitsVal.regCVal = (1 << UCSZ01); break; case DataBits::EIGHT: - dataBitsVal.ucsrcVal = (1 << UCSZ01) | (1 << UCSZ00); + dataBitsVal.regCVal = (1 << UCSZ01) | (1 << UCSZ00); break; case DataBits::NINE: - dataBitsVal.ucsrcVal = (1 << UCSZ01) | (1 << UCSZ00); - dataBitsVal.ucsrbVal = (1 << UCSZ02); + dataBitsVal.regCVal = (1 << UCSZ01) | (1 << UCSZ00); + dataBitsVal.regBVal = (1 << UCSZ02); break; } return dataBitsVal; } - template static constexpr auto calcParity() { uint8_t parityVal = 0; - if (parity == Parity::EVEN) + if (PARITY == Parity::EVEN) parityVal = (1 << UPM01); - else if (parity == Parity::ODD) + else if (PARITY == Parity::ODD) parityVal = (1 << UPM01) | (1 << UPM00); return parityVal; } - template static constexpr auto calcStopBits() { uint8_t stopBitsVal = 0; - if (stopBits == StopBits::TWO) + if (STOP_BITS == StopBits::TWO) stopBitsVal = (1 << USBS0); return stopBitsVal; } - template static constexpr auto calcMode() { static_assert(mode != Mode::SPI, "SPI mode can not be used with uart"); @@ -148,83 +189,6 @@ struct HardwareAbstraction { return enableVal; } - - static void setBaud(const uint16_t baudVal) - { - *Reg0::baudRateRegH = static_cast(baudVal >> 8); - *Reg0::baudRateRegL = static_cast(baudVal); - } - - template - static void setControlRegA() - { - *Reg0::controlStatusRegA = regVal; - } - - template - static void setControlRegB() - { - *Reg0::controlStatusRegB = regVal; - } - - template - 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 , 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() - { - detail::HardwareAbstraction hal; - hal.setBaud(hal.calcBaud()); - - constexpr auto dataBitsVal = hal.calcDataBits(); - constexpr auto parityVal = hal.calcParity(); - constexpr auto stopBitsVal = hal.calcStopBits(); - constexpr auto modeVal = hal.calcMode(); - constexpr auto enableRx = hal.calcRxState(); - constexpr auto enableTx = hal.calcTxState(); - - constexpr uint8_t ucsr0b = dataBitsVal.ucsrbVal | enableRx | enableTx; - constexpr uint8_t ucsr0c = dataBitsVal.ucsrcVal | parityVal | stopBitsVal | modeVal; - - hal.setControlRegB(); - hal.setControlRegC(); - } - - static void txByte(data_t byte) FORCE_INLINE - { - detail::HardwareAbstraction hal; - hal.txByte(byte); - } - - static data_t rxByte() {} - - static data_t peek() {} - - private: - static constexpr auto BAUD_RATE = cfg::BAUD_RATE; - static constexpr auto PARITY = cfg::PARITY; - static constexpr auto STOP_BITS = cfg::STOP_BITS; }; } // namespace uart