#pragma once #include "config.hpp" #include "hardware.hpp" #define FORCE_INLINE __attribute__((always_inline)) namespace uart { namespace detail { #if defined(__AVR_ATmega1284P__) struct Registers1 { static constexpr volatile auto *IO_REG = &UDR1; static constexpr volatile auto *CTRL_STAT_REG_A = &UCSR1A; static constexpr volatile auto *CTRL_STAT_REG_B = &UCSR1B; static constexpr volatile auto *CTRL_STAT_REG_C = &UCSR1C; static constexpr volatile auto *BAUD_REG_L = &UBRR1L; static constexpr volatile auto *BAUD_REG_H = &UBRR1H; }; enum class ControlFlagsA1 { MULTI_PROC_COMM_MODE = MPCM1, SPEED_2X = U2X1, PARITY_ERROR = UPE1, DATA_OVER_RUN = DOR1, FRAME_ERROR = FE1, DATA_REG_EMPTY = UDRE1, TRANSMIT_COMPLETE = TXC1, RECEIVE_COMPLETE = RXC1, }; enum class ControlFlagsB1 { TX_DATA_BIT_8 = TXB81, RX_DATA_BIT_8 = RXB81, CHAR_SIZE_2 = UCSZ12, TX_ENABLE = TXEN1, RX_ENABLE = RXEN1, DATA_REG_EMPTY_INT_ENABLE = UDRIE1, TX_INT_ENABLE = TXCIE1, RX_INT_ENABLE = RXCIE1, }; enum class ControlFlagsC1 { CLK_POLARITY = UCPOL1, CHAR_SIZE_0 = UCSZ10, CHAR_SIZE_1 = UCSZ11, STOP_BIT_SEL = USBS1, PARITY_MODE_0 = UPM10, PARITY_MODE_1 = UPM11, MODE_SEL_0 = UMSEL10, MODE_SEL_1 = UMSEL11, }; // clang-format off constexpr int operator<<(const int &lhs, const ControlFlagsA1 &rhs) { return lhs << static_cast(rhs); } constexpr int operator<<(const int &lhs, const ControlFlagsB1 &rhs) { return lhs << static_cast(rhs); } constexpr int operator<<(const int &lhs, const ControlFlagsC1 &rhs) { return lhs << static_cast(rhs); } // clang-format on static void (*fnRx1IntHandler)() = nullptr; static void (*fnDataReg1EmptyIntHandler)() = nullptr; static void (*fnTx1IntHandler)() = nullptr; ISR(USART1_RX_vect) { if (fnRx1IntHandler) fnRx1IntHandler(); } ISR(USART1_UDRE_vect) { if (fnDataReg1EmptyIntHandler) fnDataReg1EmptyIntHandler(); } ISR(USART1_TX_vect) { if (fnTx1IntHandler) fnTx1IntHandler(); } #define HAS_UART1 #else #error "This chip is not supported" #endif } // namespace detail #ifdef HAS_UART1 template , Driven driven = Driven::INTERRUPT> 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(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; }; 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::fnRx1IntHandler = rxIntHandler; detail::fnDataReg1EmptyIntHandler = dataRegEmptyIntHandler; 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 rxIntHandler() { // TODO } static void dataRegEmptyIntHandler() { // TODO } static void txIntHandler() { // TODO } }; #endif } // namespace uart #undef FORCE_INLINE