From 3aeb43ee1ef1d4da56c4c05935d626752dbc5c36 Mon Sep 17 00:00:00 2001 From: BlackMark Date: Fri, 2 Aug 2019 12:08:16 +0200 Subject: [PATCH] Added basic structure to support interrupt driven operation --- hardware.hpp | 19 +++++++++++--- hardware0.hpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++-- hardware1.hpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 152 insertions(+), 7 deletions(-) diff --git a/hardware.hpp b/hardware.hpp index f40eee4..415b870 100644 --- a/hardware.hpp +++ b/hardware.hpp @@ -19,7 +19,8 @@ enum class Driven { namespace detail { -template +template class Hardware { public: static void init() FORCE_INLINE @@ -35,15 +36,16 @@ class Hardware { constexpr auto modeVal = calcMode(); constexpr auto enableRx = calcRxState(); constexpr auto enableTx = calcTxState(); + constexpr auto interruptVal = calcInterrupt(); - constexpr uint8_t controlRegB = dataBitsVal.regBVal | enableRx | enableTx; + 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 void txByte(typename cfg::data_t byte) FORCE_INLINE + static void txByteBlocking(typename cfg::data_t byte) FORCE_INLINE { while (!(*Registers::CTRL_STAT_REG_A & (1 << CtrlFlagsA::DATA_REG_EMPTY))) ; @@ -146,6 +148,17 @@ class Hardware { 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) | + (1 << CtrlFlagsB::TX_INT_ENABLE); + + return interruptVal; + } }; } // namespace detail diff --git a/hardware0.hpp b/hardware0.hpp index b06cae4..a171aab 100644 --- a/hardware0.hpp +++ b/hardware0.hpp @@ -59,6 +59,28 @@ constexpr int operator<<(const int &lhs, const ControlFlagsB0 &rhs) { return lhs constexpr int operator<<(const int &lhs, const ControlFlagsC0 &rhs) { return lhs << static_cast(rhs); } // clang-format on +static void (*fnDataReg0EmptyIntHandler)() = nullptr; +static void (*fnRx0IntHandler)() = nullptr; +static void (*fnTx0IntHandler)() = nullptr; + +ISR(USART0_UDRE_vect) +{ + if (fnDataReg0EmptyIntHandler) + fnDataReg0EmptyIntHandler(); +} + +ISR(USART0_RX_vect) +{ + if (fnRx0IntHandler) + fnRx0IntHandler(); +} + +ISR(USART0_TX_vect) +{ + if (fnTx0IntHandler) + fnTx0IntHandler(); +} + #else #error "This chip is not supported" #endif @@ -78,7 +100,7 @@ class Hardware0 { static void txByte(data_t byte) FORCE_INLINE { - HardwareImpl::txByte(byte); + HardwareImpl::txByteBlocking(byte); } static data_t rxByte() FORCE_INLINE {} @@ -87,7 +109,51 @@ class Hardware0 { private: using HardwareImpl = detail::Hardware; + detail::ControlFlagsC0, cfg, mode, driven>; +}; + +template +class Hardware0 { + public: + using data_t = typename cfg::data_t; + static constexpr auto DATA_BITS = cfg::DATA_BITS; + + static void init() FORCE_INLINE + { + detail::fnDataReg0EmptyIntHandler = dataRegEmptyIntHandler; + detail::fnRx0IntHandler = rxIntHandler; + detail::fnTx0IntHandler = txIntHandler; + + HardwareImpl::init(); + } + + static void txByte(data_t byte) FORCE_INLINE + { + HardwareImpl::txByteBlocking(byte); + } + + static data_t rxByte() FORCE_INLINE {} + + static data_t peek() FORCE_INLINE {} + + private: + using HardwareImpl = detail::Hardware; + + static void dataRegEmptyIntHandler() + { + // TODO + } + + static void rxIntHandler() + { + // TODO + } + + static void txIntHandler() + { + // TODO + } }; } // namespace uart diff --git a/hardware1.hpp b/hardware1.hpp index d59f150..6e9c47b 100644 --- a/hardware1.hpp +++ b/hardware1.hpp @@ -59,6 +59,28 @@ constexpr int operator<<(const int &lhs, const ControlFlagsB1 &rhs) { return lhs constexpr int operator<<(const int &lhs, const ControlFlagsC1 &rhs) { return lhs << static_cast(rhs); } // clang-format on +static void (*fnDataReg1EmptyIntHandler)() = nullptr; +static void (*fnRx1IntHandler)() = nullptr; +static void (*fnTx1IntHandler)() = nullptr; + +ISR(USART1_UDRE_vect) +{ + if (fnDataReg1EmptyIntHandler) + fnDataReg1EmptyIntHandler(); +} + +ISR(USART1_RX_vect) +{ + if (fnRx1IntHandler) + fnRx1IntHandler(); +} + +ISR(USART1_TX_vect) +{ + if (fnTx1IntHandler) + fnTx1IntHandler(); +} + #define HAS_UART1 #else @@ -82,7 +104,7 @@ class Hardware1 { static void txByte(data_t byte) FORCE_INLINE { - HardwareImpl::txByte(byte); + HardwareImpl::txByteBlocking(byte); } static data_t rxByte() FORCE_INLINE {} @@ -91,7 +113,51 @@ class Hardware1 { private: using HardwareImpl = detail::Hardware; + detail::ControlFlagsC1, cfg, mode, driven>; +}; + +template +class Hardware1 { + public: + using data_t = typename cfg::data_t; + static constexpr auto DATA_BITS = cfg::DATA_BITS; + + static void init() FORCE_INLINE + { + detail::fnDataReg1EmptyIntHandler = dataRegEmptyIntHandler; + detail::fnRx1IntHandler = rxIntHandler; + detail::fnTx1IntHandler = txIntHandler; + + HardwareImpl::init(); + } + + static void txByte(data_t byte) FORCE_INLINE + { + HardwareImpl::txByteBlocking(byte); + } + + static data_t rxByte() FORCE_INLINE {} + + static data_t peek() FORCE_INLINE {} + + private: + using HardwareImpl = detail::Hardware; + + static void dataRegEmptyIntHandler() + { + // TODO + } + + static void rxIntHandler() + { + // TODO + } + + static void txIntHandler() + { + // TODO + } }; #endif