Refactored code to get rid of code duplication
This commit is contained in:
157
hardware1.hpp
157
hardware1.hpp
@@ -91,58 +91,24 @@ extern void (*fnDataReg1EmptyIntHandler)();
|
||||
#ifdef HAS_UART1
|
||||
|
||||
template <class cfg = Config<>, Driven driven = Driven::INTERRUPT, Mode mode = Mode::ASYNCHRONOUS>
|
||||
class Hardware1 {
|
||||
public:
|
||||
using data_t = typename cfg::data_t;
|
||||
static constexpr auto DATA_BITS = cfg::DATA_BITS;
|
||||
|
||||
static void init() FORCE_INLINE
|
||||
{
|
||||
HardwareImpl::init();
|
||||
}
|
||||
|
||||
static void txByte(const data_t &byte) FORCE_INLINE
|
||||
{
|
||||
HardwareImpl::txByteBlocking(byte);
|
||||
}
|
||||
|
||||
static bool rxByte(data_t &byte) FORCE_INLINE
|
||||
{
|
||||
return HardwareImpl::rxByteBlocking(byte);
|
||||
}
|
||||
|
||||
static bool peek(data_t &byte) FORCE_INLINE
|
||||
{
|
||||
static_cast<void>(byte);
|
||||
static_assert(driven != Driven::BLOCKING, "Peek with data is not supported in blocking mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool peek() FORCE_INLINE
|
||||
{
|
||||
return HardwareImpl::peekBlocking();
|
||||
}
|
||||
|
||||
static void flushTx() FORCE_INLINE
|
||||
{
|
||||
while (!HardwareImpl::txEmpty())
|
||||
;
|
||||
while (!HardwareImpl::txComplete())
|
||||
;
|
||||
HardwareImpl::clearTxComplete();
|
||||
}
|
||||
|
||||
private:
|
||||
using HardwareImpl = detail::Hardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
|
||||
detail::ControlFlagsC1, cfg, driven, mode>;
|
||||
class Hardware1 : public detail::BlockingHardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
|
||||
detail::ControlFlagsC1, cfg, mode> {
|
||||
};
|
||||
|
||||
template <class cfg, Mode mode>
|
||||
class Hardware1<cfg, Driven::INTERRUPT, mode> {
|
||||
public:
|
||||
using data_t = typename cfg::data_t;
|
||||
static constexpr auto DATA_BITS = cfg::DATA_BITS;
|
||||
class Hardware1<cfg, Driven::INTERRUPT, mode>
|
||||
: public detail::InterruptHardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
|
||||
detail::ControlFlagsC1, cfg, mode> {
|
||||
using detail::InterruptHardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
|
||||
detail::ControlFlagsC1, cfg, mode>::rxIntHandler;
|
||||
|
||||
using detail::InterruptHardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
|
||||
detail::ControlFlagsC1, cfg, mode>::dataRegEmptyIntHandler;
|
||||
|
||||
using HardwareImpl = detail::Hardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
|
||||
detail::ControlFlagsC1, cfg, Driven::INTERRUPT, mode>;
|
||||
|
||||
public:
|
||||
static void init() FORCE_INLINE
|
||||
{
|
||||
detail::fnRx1IntHandler = rxIntHandler;
|
||||
@@ -151,103 +117,8 @@ class Hardware1<cfg, Driven::INTERRUPT, mode> {
|
||||
HardwareImpl::init();
|
||||
sei();
|
||||
}
|
||||
|
||||
static void txByte(const data_t &byte) FORCE_INLINE
|
||||
{
|
||||
uint8_t tmpHead = (sm_txBuf.head + 1) % TX_BUFFER_SIZE;
|
||||
while (tmpHead == sm_txBuf.tail)
|
||||
;
|
||||
|
||||
sm_txBuf.buf[tmpHead] = byte;
|
||||
sm_txBuf.head = tmpHead;
|
||||
|
||||
HardwareImpl::enableDataRegEmptyInt();
|
||||
}
|
||||
|
||||
static bool rxByte(data_t &byte) FORCE_INLINE
|
||||
{
|
||||
if (sm_rxBuf.head == sm_rxBuf.tail)
|
||||
return false;
|
||||
|
||||
uint8_t tmpTail = (sm_rxBuf.tail + 1) % RX_BUFFER_SIZE;
|
||||
byte = sm_rxBuf.buf[tmpTail];
|
||||
sm_rxBuf.tail = tmpTail;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool peek(data_t &byte) FORCE_INLINE
|
||||
{
|
||||
if (sm_rxBuf.head == sm_rxBuf.tail)
|
||||
return false;
|
||||
|
||||
uint8_t tmpTail = (sm_rxBuf.tail + 1) % RX_BUFFER_SIZE;
|
||||
byte = sm_rxBuf.buf[tmpTail];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool peek() FORCE_INLINE
|
||||
{
|
||||
return (sm_rxBuf.head != sm_rxBuf.tail);
|
||||
}
|
||||
|
||||
static void flushTx() FORCE_INLINE
|
||||
{
|
||||
while (sm_txBuf.head != sm_txBuf.tail)
|
||||
;
|
||||
while (!HardwareImpl::txEmpty())
|
||||
;
|
||||
while (!HardwareImpl::txComplete())
|
||||
;
|
||||
HardwareImpl::clearTxComplete();
|
||||
}
|
||||
|
||||
private:
|
||||
using HardwareImpl = detail::Hardware<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
|
||||
detail::ControlFlagsC1, cfg, Driven::INTERRUPT, mode>;
|
||||
|
||||
static constexpr auto TX_BUFFER_SIZE = 16;
|
||||
static constexpr auto RX_BUFFER_SIZE = 16;
|
||||
|
||||
static volatile detail::RingBuffer<data_t, TX_BUFFER_SIZE> sm_txBuf;
|
||||
static volatile detail::RingBuffer<data_t, RX_BUFFER_SIZE> sm_rxBuf;
|
||||
|
||||
static void rxIntHandler()
|
||||
{
|
||||
auto data = HardwareImpl::rxByteInterrupt();
|
||||
|
||||
uint8_t tmpHead = (sm_rxBuf.head + 1) % RX_BUFFER_SIZE;
|
||||
|
||||
if (tmpHead != sm_rxBuf.tail) {
|
||||
sm_rxBuf.head = tmpHead;
|
||||
sm_rxBuf.buf[tmpHead] = data;
|
||||
} else {
|
||||
// TODO: Handle overflow
|
||||
}
|
||||
}
|
||||
|
||||
static void dataRegEmptyIntHandler() FORCE_INLINE
|
||||
{
|
||||
if (sm_txBuf.head != sm_txBuf.tail) {
|
||||
uint8_t tmpTail = (sm_txBuf.tail + 1) % TX_BUFFER_SIZE;
|
||||
sm_txBuf.tail = tmpTail;
|
||||
HardwareImpl::txByteInterrupt(sm_txBuf.buf[tmpTail]);
|
||||
} else
|
||||
HardwareImpl::disableDataRegEmptyInt();
|
||||
}
|
||||
};
|
||||
|
||||
template <class cfg, Mode mode>
|
||||
volatile detail::RingBuffer<typename Hardware1<cfg, Driven::INTERRUPT, mode>::data_t,
|
||||
Hardware1<cfg, Driven::INTERRUPT, mode>::TX_BUFFER_SIZE>
|
||||
Hardware1<cfg, Driven::INTERRUPT, mode>::sm_txBuf = {0, 0, {0}};
|
||||
|
||||
template <class cfg, Mode mode>
|
||||
volatile detail::RingBuffer<typename Hardware1<cfg, Driven::INTERRUPT, mode>::data_t,
|
||||
Hardware1<cfg, Driven::INTERRUPT, mode>::RX_BUFFER_SIZE>
|
||||
Hardware1<cfg, Driven::INTERRUPT, mode>::sm_rxBuf = {0, 0, {0}};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace uart
|
||||
|
||||
Reference in New Issue
Block a user