Added basic structure to support interrupt driven operation

This commit is contained in:
BlackMark 2019-08-02 12:08:16 +02:00
parent a13a1ca9ab
commit 3aeb43ee1e
3 changed files with 152 additions and 7 deletions

View File

@ -19,7 +19,8 @@ enum class Driven {
namespace detail {
template <class Registers, typename CtrlFlagsA, typename CtrlFlagsB, typename CtrlFlagsC, class cfg, Mode mode>
template <class Registers, typename CtrlFlagsA, typename CtrlFlagsB, typename CtrlFlagsC, class cfg, Mode mode,
Driven driven>
class Hardware {
public:
static void init() FORCE_INLINE
@ -35,15 +36,16 @@ class Hardware {
constexpr auto modeVal = calcMode();
constexpr auto enableRx = calcRxState<true>();
constexpr auto enableTx = calcTxState<true>();
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

View File

@ -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<int>(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::Registers0, detail::ControlFlagsA0, detail::ControlFlagsB0,
detail::ControlFlagsC0, cfg, mode>;
detail::ControlFlagsC0, cfg, mode, driven>;
};
template <Mode mode, class cfg>
class Hardware0<mode, cfg, Driven::INTERRUPT> {
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<detail::Registers0, detail::ControlFlagsA0, detail::ControlFlagsB0,
detail::ControlFlagsC0, cfg, mode, Driven::INTERRUPT>;
static void dataRegEmptyIntHandler()
{
// TODO
}
static void rxIntHandler()
{
// TODO
}
static void txIntHandler()
{
// TODO
}
};
} // namespace uart

View File

@ -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<int>(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::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
detail::ControlFlagsC1, cfg, mode>;
detail::ControlFlagsC1, cfg, mode, driven>;
};
template <Mode mode, class cfg>
class Hardware1<mode, cfg, Driven::INTERRUPT> {
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<detail::Registers1, detail::ControlFlagsA1, detail::ControlFlagsB1,
detail::ControlFlagsC1, cfg, mode, Driven::INTERRUPT>;
static void dataRegEmptyIntHandler()
{
// TODO
}
static void rxIntHandler()
{
// TODO
}
static void txIntHandler()
{
// TODO
}
};
#endif