Prusa-MMU-Private
PrusaMultiMaterialUpgradev3firmwareforMK3SMK4
usart.h
Go to the documentation of this file.
1 #pragma once
3 #include <inttypes.h>
4 #include <avr/io.h>
5 #include "gpio.h"
6 #include "circular_buffer.h"
7 
8 namespace hal {
9 
13 namespace usart {
14 
15 constexpr uint16_t UART_BAUD_SELECT(uint32_t baudRate, uint32_t xtalCpu) {
16  return (((double)(xtalCpu)) / (((double)(baudRate)) * 8.0) - 1.0 + 0.5);
17 }
18 
19 class USART {
20 public:
21  struct USART_TypeDef {
22  volatile uint8_t UCSRxA;
23  volatile uint8_t UCSRxB;
24  volatile uint8_t UCSRxC;
25  volatile uint8_t UCSRxD;
26  volatile uint16_t UBRRx;
27  volatile uint8_t UDRx;
28  };
29 
31  hal::gpio::GPIO_pin rx_pin;
32  hal::gpio::GPIO_pin tx_pin;
33  uint32_t baudrate;
34  };
35 
37  uint8_t Peek() const {
38  return rx_buf.front();
39  }
41  bool ReadEmpty() const {
42  return rx_buf.empty();
43  }
45  uint8_t Read();
46 
48  void Write(uint8_t c);
51  void WriteS(const char *str);
54  void WriteS_P(const char *str_P);
55 
58  void puts(const char *str);
61  void puts_P(const char *str_P);
63  bool CanWrite() const {
64  return !tx_buf.full();
65  }
67  void Flush();
68 
70  __attribute__((always_inline)) inline void rx_enable() { husart->UCSRxB |= (1 << RXEN1); };
71 
73  __attribute__((always_inline)) inline void Init(USART_InitTypeDef *const conf) {
74  gpio::Init(conf->rx_pin, gpio::GPIO_InitTypeDef(gpio::Mode::input, gpio::Level::low));
75  gpio::Init(conf->tx_pin, gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::low));
76  husart->UBRRx = UART_BAUD_SELECT(conf->baudrate, F_CPU);
77  husart->UCSRxA |= (1 << U2X1); // Set double baudrate setting. Clear all other status bits/flags
78  // husart->UCSRxC |= (1 << 3); // 2 stop bits. Preserve data size setting
79  husart->UCSRxD = 0; // disable hardware flow control. Few avr MCUs have this feature, but this register is reserved on all AVR devices with USART, so we can disable it without consequences.
80  husart->UCSRxB = (1 << TXEN1) | (1 << RXCIE1); // Turn on the transmission and reception circuitry and enable the RX interrupt
81  }
82 
84  __attribute__((always_inline)) inline void ISR_RX() {
85  if (husart->UCSRxA & (1 << FE1)) {
86  (void)husart->UDRx;
87  } else {
88  rx_buf.push((uint8_t)husart->UDRx);
89  }
90  }
92  __attribute__((always_inline)) inline void ISR_UDRE() {
93  uint8_t c = 0;
94  tx_buf.pop(c);
95  husart->UDRx = c;
96 
97  // clear the TXC bit -- "can be cleared by writing a one to its bit
98  // location". This makes sure flush() won't return until the bytes
99  // actually got written
100  husart->UCSRxA |= (1 << TXC1);
101 
102  if (tx_buf.empty())
103  husart->UCSRxB &= ~(1 << UDRIE1); // disable UDRE interrupt
104  }
105 
106  USART(USART_TypeDef *husart)
107  : husart(husart) {};
108 
109 private:
110  // IO base address
111  USART_TypeDef *husart;
112  bool _written;
113 
116 };
117 
119 extern USART usart1;
120 
121 } // namespace usart
122 } // namespace hal
123 
124 #define USART1 ((hal::usart::USART::USART_TypeDef *)&UCSR1A)
125 
126 namespace hu = hal::usart;
bool pop(T &elem)
Definition: circular_buffer.h:135
bool push(T elem)
Definition: circular_buffer.h:119
T front() const
Definition: circular_buffer.h:129
Definition: usart.h:19
__attribute__((always_inline)) inline void rx_enable()
Enable the RX receiver.
Definition: usart.h:70
void Flush()
blocks until the TX buffer was successfully transmitted
Definition: usart.cpp:48
void puts(const char *str)
Definition: usart.cpp:82
uint8_t Read()
Definition: usart.cpp:11
bool CanWrite() const
Definition: usart.h:63
void WriteS(const char *str)
Definition: usart.cpp:69
__attribute__((always_inline)) inline void Init(USART_InitTypeDef *const conf)
Initializes USART interface.
Definition: usart.h:73
void puts_P(const char *str_P)
Definition: usart.cpp:87
void Write(uint8_t c)
Definition: usart.cpp:17
void WriteS_P(const char *str_P)
Definition: usart.cpp:75
uint8_t Peek() const
Definition: usart.h:37
__attribute__((always_inline)) inline void ISR_RX()
implementation of the receive ISR's body
Definition: usart.h:84
bool ReadEmpty() const
Definition: usart.h:41
__attribute__((always_inline)) inline void ISR_UDRE()
implementation of the transmit ISR's body
Definition: usart.h:92
#define F_CPU
Main clock frequency.
Definition: cpu.h:11
void Init()
ADC access routines.
Definition: adc.cpp:8
Definition: usart.cpp:7
USART usart1(USART1)
beware - normally we'd make a singleton, but avr-gcc generates suboptimal code for them,...
Definition: usart.h:119
Definition: gpio.h:39
Definition: gpio.h:51
Definition: usart.h:21