diff --git a/hardware.hpp b/hardware.hpp index 415b870..b8f553d 100644 --- a/hardware.hpp +++ b/hardware.hpp @@ -45,7 +45,7 @@ class Hardware { *Registers::CTRL_STAT_REG_C = controlRegC; } - static void txByteBlocking(typename cfg::data_t byte) FORCE_INLINE + static void txByteBlocking(const typename cfg::data_t &byte) FORCE_INLINE { while (!(*Registers::CTRL_STAT_REG_A & (1 << CtrlFlagsA::DATA_REG_EMPTY))) ; @@ -53,6 +53,21 @@ class Hardware { *Registers::IO_REG = byte; } + static void txByteInterrupt(volatile const typename cfg::data_t &byte) FORCE_INLINE + { + *Registers::IO_REG = byte; + } + + static void enableDataRegEmptyInt() FORCE_INLINE + { + *Registers::CTRL_STAT_REG_B |= (1 << CtrlFlagsB::DATA_REG_EMPTY_INT_ENABLE); + } + + static void disableDataRegEmptyInt() FORCE_INLINE + { + *Registers::CTRL_STAT_REG_B &= ~(1 << CtrlFlagsB::DATA_REG_EMPTY_INT_ENABLE); + } + private: struct DataBitsVal { uint8_t regCVal = 0; diff --git a/hardware0.hpp b/hardware0.hpp index 848bbdc..521aac6 100644 --- a/hardware0.hpp +++ b/hardware0.hpp @@ -127,9 +127,16 @@ class Hardware0 { HardwareImpl::init(); } - static void txByte(data_t byte) FORCE_INLINE + static void txByte(const data_t &byte) FORCE_INLINE { - HardwareImpl::txByteBlocking(byte); + uint8_t tmpHead = (sm_txHead + 1) % TX_BUFFER_SIZE; + while (tmpHead == sm_txTail) + ; + + sm_txBuffer[tmpHead] = byte; + sm_txHead = tmpHead; + + HardwareImpl::enableDataRegEmptyInt(); } static data_t rxByte() FORCE_INLINE {} @@ -140,14 +147,25 @@ class Hardware0 { using HardwareImpl = detail::Hardware; + static constexpr auto TX_BUFFER_SIZE = 16; + + static volatile uint8_t sm_txHead; + static volatile uint8_t sm_txTail; + static volatile data_t sm_txBuffer[TX_BUFFER_SIZE]; + static void rxIntHandler() { // TODO } - static void dataRegEmptyIntHandler() + static void dataRegEmptyIntHandler() FORCE_INLINE { - // TODO + if (sm_txHead != sm_txTail) { + uint8_t tmpTail = (sm_txTail + 1) % TX_BUFFER_SIZE; + sm_txTail = tmpTail; + HardwareImpl::txByteInterrupt(sm_txBuffer[tmpTail]); + } else + HardwareImpl::disableDataRegEmptyInt(); } static void txIntHandler() @@ -156,6 +174,14 @@ class Hardware0 { } }; +template +volatile uint8_t Hardware0::sm_txHead = 0; +template +volatile uint8_t Hardware0::sm_txTail = 0; +template +volatile typename Hardware0::data_t + Hardware0::sm_txBuffer[TX_BUFFER_SIZE]; + } // namespace uart #undef FORCE_INLINE diff --git a/hardware1.hpp b/hardware1.hpp index 78b28ca..b053fdc 100644 --- a/hardware1.hpp +++ b/hardware1.hpp @@ -102,7 +102,7 @@ class Hardware1 { HardwareImpl::init(); } - static void txByte(data_t byte) FORCE_INLINE + static void txByte(const data_t &byte) FORCE_INLINE { HardwareImpl::txByteBlocking(byte); } @@ -131,9 +131,16 @@ class Hardware1 { HardwareImpl::init(); } - static void txByte(data_t byte) FORCE_INLINE + static void txByte(const data_t &byte) FORCE_INLINE { - HardwareImpl::txByteBlocking(byte); + uint8_t tmpHead = (sm_txHead + 1) % TX_BUFFER_SIZE; + while (tmpHead == sm_txTail) + ; + + sm_txBuffer[tmpHead] = byte; + sm_txHead = tmpHead; + + HardwareImpl::enableDataRegEmptyInt(); } static data_t rxByte() FORCE_INLINE {} @@ -144,14 +151,25 @@ class Hardware1 { using HardwareImpl = detail::Hardware; + static constexpr auto TX_BUFFER_SIZE = 16; + + static volatile uint8_t sm_txHead; + static volatile uint8_t sm_txTail; + static volatile data_t sm_txBuffer[TX_BUFFER_SIZE]; + static void rxIntHandler() { // TODO } - static void dataRegEmptyIntHandler() + static void dataRegEmptyIntHandler() FORCE_INLINE { - // TODO + if (sm_txHead != sm_txTail) { + uint8_t tmpTail = (sm_txTail + 1) % TX_BUFFER_SIZE; + sm_txTail = tmpTail; + HardwareImpl::txByteInterrupt(sm_txBuffer[tmpTail]); + } else + HardwareImpl::disableDataRegEmptyInt(); } static void txIntHandler() @@ -160,6 +178,14 @@ class Hardware1 { } }; +template +volatile uint8_t Hardware1::sm_txHead = 0; +template +volatile uint8_t Hardware1::sm_txTail = 0; +template +volatile typename Hardware1::data_t + Hardware1::sm_txBuffer[TX_BUFFER_SIZE]; + #endif } // namespace uart