284 lines
5.6 KiB
C++
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;
|
|
}
|