+static void spi_starttx(struct SerialHardware *_hw)
+{
+ struct AvrSerial *hw = (struct AvrSerial *)_hw;
+
+ cpuflags_t flags;
+ DISABLE_IRQSAVE(flags);
+
+ /* Send data only if the SPI is not already transmitting */
+ if (!hw->sending && !fifo_isempty(&ser_spi->txfifo))
+ {
+ hw->sending = true;
+ SPDR = fifo_pop(&ser_spi->txfifo);
+ }
+
+ ENABLE_IRQRESTORE(flags);
+}
+
+static void spi_setbaudrate(UNUSED(struct SerialHardware *, _hw), UNUSED(unsigned long, rate))
+{
+ // nop
+}
+
+static void spi_setparity(UNUSED(struct SerialHardware *, _hw), UNUSED(int, parity))
+{
+ // nop
+}
+
+
+
+/*
+ * High-level interface data structures
+ */
+static const struct SerialHardwareVT UART0_VT =
+{
+ .init = uart0_init,
+ .cleanup = uart0_cleanup,
+ .setbaudrate = uart0_setbaudrate,
+ .setparity = uart0_setparity,
+ .enabletxirq = uart0_enabletxirq,
+};
+
+#if AVR_HAS_UART1
+static const struct SerialHardwareVT UART1_VT =
+{
+ .init = uart1_init,
+ .cleanup = uart1_cleanup,
+ .setbaudrate = uart1_setbaudrate,
+ .setparity = uart1_setparity,
+ .enabletxirq = uart1_enabletxirq,
+};
+#endif // AVR_HAS_UART1
+
+static const struct SerialHardwareVT SPI_VT =
+{
+ .init = spi_init,
+ .cleanup = spi_cleanup,
+ .setbaudrate = spi_setbaudrate,
+ .setparity = spi_setparity,
+ .enabletxirq = spi_starttx,
+};
+
+static struct AvrSerial UARTDescs[SER_CNT] =
+{
+ {
+ .hw = {
+ .table = &UART0_VT,
+ .txbuffer = uart0_txbuffer,
+ .rxbuffer = uart0_rxbuffer,
+ .txbuffer_size = CONFIG_UART0_TXBUFSIZE,
+ .rxbuffer_size = CONFIG_UART0_RXBUFSIZE,
+ },
+ .sending = false,
+ },
+#if AVR_HAS_UART1
+ {
+ .hw = {
+ .table = &UART1_VT,
+ .txbuffer = uart1_txbuffer,
+ .rxbuffer = uart1_rxbuffer,
+ .txbuffer_size = CONFIG_UART1_TXBUFSIZE,
+ .rxbuffer_size = CONFIG_UART1_RXBUFSIZE,
+ },
+ .sending = false,
+ },
+#endif
+ {
+ .hw = {
+ .table = &SPI_VT,
+ .txbuffer = spi_txbuffer,
+ .rxbuffer = spi_rxbuffer,
+ .txbuffer_size = CONFIG_SPI_TXBUFSIZE,
+ .rxbuffer_size = CONFIG_SPI_RXBUFSIZE,
+ },
+ .sending = false,
+ }
+};
+
+struct SerialHardware* ser_hw_getdesc(int unit)
+{
+ ASSERT(unit < SER_CNT);
+ return &UARTDescs[unit].hw;
+}
+