uart/uart/main.cpp

284 lines
5.6 KiB
C++

#include "clock.hpp"
#include <avr/interrupt.h>
#include <stdint.h>
#include "flash/flash.hpp"
#include "io/io.hpp"
#include "uart/uart.hpp"
using uart0_interface_t =
uart::Uart<uart::Hardware0<uart::Config<115200>, uart::Driven::INTERRUPT, uart::Mode::ASYNCHRONOUS>>;
using uart1_interface_t = uart::Uart1<>;
REGISTER_UART0_INT_VECTORS(uart0_interface_t);
REGISTER_UART1_INT_VECTORS(uart1_interface_t);
void doubleSpeedTest()
{
uart0_interface_t serial;
serial.init();
uint8_t counter = 100;
uint8_t data;
while (counter) {
if (serial.rxByte(data)) {
serial.txByte(data);
--counter;
}
}
serial << F("\r\n");
serial.flushTx();
}
void newUartUsage()
{
using namespace uart;
Uart<Hardware0<Config<115200>, Driven::BLOCKING, Mode::ASYNCHRONOUS>> serial;
serial.init();
serial << "New uart hi from RAM. " << F("New uart hi from flash\r\n");
while (false) {
uint8_t received = 0;
while (!serial.peek())
;
{
serial << F("Peeked: ");
serial.txByte(received);
serial << F("\r\n");
}
if (serial.rxByte(received)) {
serial << F("Received: ");
serial.txByte(received);
serial << F("\r\n");
}
}
serial.flushTx();
}
void newUartUsage2()
{
uart1_interface_t serial1;
auto ramString = "Hello World from RAM. ";
auto flashString = F("Hello World from flash\r\n");
serial1.init();
serial1 << ramString;
serial1 << flashString;
serial1.flushTx();
}
void newUartStreamOverloads()
{
using namespace uart;
Uart<Hardware0<Config<115200>, Driven::BLOCKING, Mode::ASYNCHRONOUS>> serial;
serial.init();
bool bVal = true;
char chVal = 'c';
signed char schVal = 's';
unsigned char uchVal = 'u';
short shVal = -12345;
unsigned short ushVal = 64123;
int iVal = -14321;
unsigned int uiVal = 32146;
long lVal = -571474496;
unsigned long ulVal = 2718958144;
long long llVal = -45197516864960;
unsigned long long ullVal = 4611685969606738496;
serial << F("Stream overload test:") << F("\r\n");
serial << F("bool : ") << bVal << F("\r\n");
serial << F("char : ") << chVal << F("\r\n");
serial << F("signed char : ") << schVal << F("\r\n");
serial << F("unsigned char : ") << uchVal << F("\r\n");
serial << F("short : ") << shVal << F("\r\n");
serial << F("unsigned short : ") << ushVal << F("\r\n");
serial << F("int : ") << iVal << F("\r\n");
serial << F("unsigned int : ") << uiVal << F("\r\n");
serial << F("long : ") << lVal << F("\r\n");
serial << F("unsigned long : ") << ulVal << F("\r\n");
serial << F("long long : ") << llVal << F("\r\n");
serial << F("unsigned long long : ") << ullVal << F("\r\n");
serial << F("const void : ") << &bVal << F("\r\n");
auto number = 0xBADF00D;
serial << F("Binary : 0b");
serial.txNumber<decltype(number), 2>(number);
serial << F("\r\n");
serial << F("Octal : 0");
serial.txNumber<decltype(number), 8>(number);
serial << F("\r\n");
serial << F("Decimal : ");
serial.txNumber<decltype(number), 10>(number);
serial << F("\r\n");
serial << F("Hex : 0x");
serial.txNumber<decltype(number), 16>(number);
serial << F("\r\n");
serial.flushTx();
}
namespace spi {
enum class Cpol {
MODE_0,
MODE_1,
};
enum class Cpha {
MODE_0,
MODE_1,
};
enum class DataOrder {
MSB,
LSB,
};
template <Cpol cpol, Cpha cpha, DataOrder dataOrder>
struct Config {
static constexpr auto CPOL_MODE = cpol;
static constexpr auto CPHA_MODE = cpha;
static constexpr auto DATA_ORDER = dataOrder;
};
template <class Driver>
struct spi {
spi()
{
Driver::init();
}
};
} // namespace spi
namespace uart {
template <class Config>
class Hardware0<Config, Driven::INTERRUPT, Mode::SPI> {
public:
static void init()
{
UCSR0C |= (1 << UMSEL01) | (1 << UMSEL00);
if (DATA_ORDER == spi::DataOrder::MSB)
UCSR0C &= ~(1 << UCSZ01);
else
UCSR0C |= (1 << UCSZ01);
if (CPOL_MODE == spi::Cpol::MODE_0)
UCSR0C &= ~(1 << UCPOL0);
else
UCSR0C |= (1 << UCPOL0);
if (CPHA_MODE == spi::Cpha::MODE_0)
UCSR0C &= ~(1 << UCSZ00);
else
UCSR0C |= (1 << UCSZ00);
}
private:
static constexpr auto CPOL_MODE = Config::CPOL_MODE;
static constexpr auto CPHA_MODE = Config::CPHA_MODE;
static constexpr auto DATA_ORDER = Config::DATA_ORDER;
};
} // namespace uart
void spiTest()
{
using config = spi::Config<spi::Cpol::MODE_0, spi::Cpha::MODE_0, spi::DataOrder::MSB>;
using uartspi = uart::Hardware0<config, uart::Driven::INTERRUPT, uart::Mode::SPI>;
spi::spi<uartspi> uartSpi;
}
static inline void initUart(const uint32_t baudRate)
{
UBRR0 = static_cast<uint16_t>((F_CPU + 8 * baudRate) / (16 * baudRate) - 1);
UCSR0A = 0;
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
}
static inline void txUart(uint8_t byte)
{
while (!(UCSR0A & (1 << UDRE0)))
;
UDR0 = byte;
}
static inline void txString(const char *str)
{
while (char ch = *str++)
txUart(ch);
}
static inline void txString(const detail::FlashString *str)
{
const char *strIt = reinterpret_cast<const char *>(str);
while (char ch = pgm_read_byte(strIt++))
txUart(ch);
}
static inline void flushTx()
{
while (!(UCSR0A & (1 << UDRE0)))
;
while (!(UCSR0A & (1 << TXC0)))
;
UCSR0A |= (1 << TXC0);
}
void optimalUartTest()
{
auto ramString = "Hello World from RAM. ";
auto flashString = F("Hello World from flash\r\n");
initUart(115200);
txString(ramString);
txString(flashString);
flushTx();
}
int main()
{
sei();
doubleSpeedTest();
newUartUsage2();
optimalUartTest();
newUartStreamOverloads();
txString(F("\r\n"));
flushTx();
spiTest();
return 0;
}