diff --git a/uart/main.cpp b/uart/main.cpp index 19625f8..09cd3df 100644 --- a/uart/main.cpp +++ b/uart/main.cpp @@ -2,21 +2,235 @@ #include +#include + #include "flash/flash.hpp" +#include "io/io.hpp" +#include "uart/uart.hpp" #include "uart/usart.h" -int main() +namespace uart_test { + +enum class Mode { ASYNCHRONOUS = 0, SYNCHRONOUS = 1, MASTERSPI = 2 }; + +enum class Parity { DISABLED = 0, ODD = 1, EVEN = 2 }; + +enum class StopBit { ONE = 1, TWO = 2 }; + +template +class hardware0 { + static constexpr auto calcBaud() + { + uint16_t ui16UBRR = ((F_CPU / (16 * baudRate)) - 1); + return ui16UBRR; + } + + public: + static void setBaud() + { + constexpr auto ui16UBRR = calcBaud(); + + UBRR0H = static_cast(ui16UBRR >> 8); + UBRR0L = static_cast(ui16UBRR); + } + + static void setDataBits() + { + uint8_t ui8UCSRC = UCSR0C; + uint8_t ui8DataBits = dataBits; + + if (ui8DataBits < 5) { + ui8DataBits = 5; + } else if (ui8DataBits > 9) { + ui8DataBits = 9; + } + + if (ui8DataBits <= 8) { + bool bZeroBit = (ui8DataBits - 5) & 1; + bool bOneBit = ((ui8DataBits - 5) >> 1) & 1; + + if (bZeroBit) { + ui8UCSRC |= (1 << UCSZ00); + } else { + ui8UCSRC &= ~(1 << UCSZ00); + } + + if (bOneBit) { + ui8UCSRC |= (1 << UCSZ01); + } else { + ui8UCSRC &= ~(1 << UCSZ01); + } + + UCSR1B &= ~(1 << UCSZ02); + } else { + ui8UCSRC |= (1 << UCSZ01) | (1 << UCSZ00); + UCSR1B |= (1 << UCSZ02); + } + + UCSR0C = ui8UCSRC; + } + + static void setParity() + { + uint8_t ui8UCSRC = UCSR0C; + + if (parity == Parity::DISABLED) { + ui8UCSRC &= ~((1 << UPM01) | (1 << UPM00)); + } else if (parity == Parity::ODD) { + ui8UCSRC |= ((1 << UPM01) | (1 << UPM00)); + } else if (parity == Parity::EVEN) { + ui8UCSRC &= ~((1 << UPM00)); + ui8UCSRC |= ((1 << UPM01)); + } + + UCSR0C = ui8UCSRC; + } + + static void setStopBit() + { + uint8_t ui8UCSRC = UCSR0C; + + if (stopBit == StopBit::ONE) { + ui8UCSRC &= ~(1 << USBS0); + } else if (stopBit == StopBit::TWO) { + ui8UCSRC |= (1 << USBS0); + } + + UCSR0C = ui8UCSRC; + } + + static void setMode() + { + uint8_t ui8UCSRC = UCSR0C; + + if (mode == Mode::ASYNCHRONOUS) { + ui8UCSRC &= ~((1 << UMSEL01) | (1 << UMSEL00)); + } else if (mode == Mode::SYNCHRONOUS) { + ui8UCSRC &= ~(1 << UMSEL01); + ui8UCSRC |= (1 << UMSEL00); + } else if (mode == Mode::MASTERSPI) { + ui8UCSRC |= ((1 << UMSEL01) | (1 << UMSEL00)); + } + + UCSR0C = ui8UCSRC; + } + + static void setRXState(bool state) + { + if (state) { + UCSR0B |= (1 << RXEN0); + } else { + UCSR0B &= ~(1 << RXEN0); + } + } + + static void setTXState(bool state) + { + if (state) { + UCSR0B |= (1 << TXEN0); + } else { + UCSR0B &= ~(1 << TXEN0); + } + } + + static void txByte(uint8_t ui8Data) + { + while (!(UCSR0A & (1 << UDRE0))) + ; + UDR0 = ui8Data; + } +}; + +template +class uart { + public: + uart() = default; + uart(const uart &) = delete; + uart(uart &&) = delete; + uart &operator=(const uart &) = delete; + uart &operator=(uart &&) = delete; + + static void init() + { + driver::setBaud(); + driver::setDataBits(); + driver::setParity(); + driver::setStopBit(); + driver::setMode(); + + driver::setRXState(true); + driver::setTXState(true); + } + + uart &operator<<(const char *str) + { + while (char ch = *str++) + driver::txByte(ch); + + return *this; + } + + uart &operator<<(const detail::FlashString *str) + { + const char *strIt = reinterpret_cast(str); + + while (char ch = pgm_read_byte(strIt++)) + driver::txByte(ch); + + return *this; + } +}; + +} // namespace uart_test + +void usartTestUsage() +{ + using uart0 = uart_test::hardware0<9600, 8, uart_test::Parity::DISABLED, uart_test::StopBit::ONE, + uart_test::Mode::ASYNCHRONOUS>; + + /*using softuart = uart::Device, 9600, 8, uart::Parity::DISABLED, + uart::StopBit::ONE, uart::Mode::ASYNCHRONOUS>;*/ + + uart_test::uart serial0; + // uart::uart softSerial; + + serial0.init(); + + auto endl = F(" And greets from flash!\r\n"); + + serial0 << "Hello World from hardware serial 0!" << endl; + + _delay_ms(1000); + + // softSerial << "Hello World from software serial on PB0 and PB1" << F("\r\n"); +} + +void newUartUsage() +{ + using settings = uart::settings<9600, uart::DataBits::EIGHT, uart::Parity::NONE, uart::StopBits::ONE>; + using uart0 = uart::detail::hardware0; + + uart::uart serial; + + serial << "Hello World using finalized interface!" << F("\r\nAlso works from progmem\r\n"); +} + +void oldUsartUsage() { USART0 &serial = USART0::inst(); serial.init(9600); - sei(); - while (true) { - serial << "Hello World!" - << "\r\n"; + serial << "Hello World from hardware serial 0!" + << " And greets from ram:(!\r\n"; - _delay_ms(1000); - } + _delay_ms(1000); +} + +int main() +{ + usartTestUsage(); + newUartUsage(); + oldUsartUsage(); return 0; } diff --git a/uart/uart b/uart/uart index 81e6a9f..f9c34b0 160000 --- a/uart/uart +++ b/uart/uart @@ -1 +1 @@ -Subproject commit 81e6a9fdc0c588712b4a1b1598a927326d282c53 +Subproject commit f9c34b09bad1c65d2dfaf5a9ae7e128b3719b321 diff --git a/uart/uart.cppproj b/uart/uart.cppproj index 2223ecc..b61b2d5 100644 --- a/uart/uart.cppproj +++ b/uart/uart.cppproj @@ -205,6 +205,21 @@ compile + + compile + + + compile + + + compile + + + compile + + + compile + compile