continuing the discussion from
https://www.avrfreaks.net/index.p...
This UART interrupt code for C++ is an unbuffered UART ISR. It overloads the "display" function (if my jargon is right). A ring-buffered version uses the code, below, to derive a buffered "display", again overloading. And something similar for UART input.
What I see missing in this ISR is the customary UART transmit interrupt- where the transmit ISR pulls the next byte from the ring buffer and sends it to the chip, then dismisses the interrupt. If there are no more bytes in the buffer, the ISR customarily sets a flag to tell the non-interrupt code that it must later store the first byte in the hardware to cause the first interrupt; then clear the flag.
the code
m_readyToTx(true);
seems to set a flag that the ISR occurred due to transmit complete, but the ISR didn't pull the next byte and send to hardware. Or did it.
All this arcane code, overloading, etc. for OOP, to me yields very non-obvious code and invisible actions. This seems contrary to what I like to code: blatantly obvious what's happening so I (or others) can understand the code a year later. Gee, I don't even like C macros for the same reason!
But I will press on, with help from you guys, and hope others can benefit.
/* * Uart.cpp */ #include "Uart.hpp" #includestatic UART* s_uart[1]; // Create a UART with no buffers UART::UART(uint32_t baud, FuncPtru08 rx_func) : DISPLAY(), m_readyToTx(true), m_rx_func(rx_func) { s_uart[0]=this; // enable transmit, receive and interrupts outb(UCR, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN)); SetBaudRate(baud); sei(); } void UART::display(uint8_t c){ // wait for the transmitter to be ready while(!m_readyToTx) {}; // send byte m_readyToTx = false; outb(UDR, c); // set ready state to FALSE //m_readyToTx = false; // the byte will be sent in the background } // UART Transmit complete UART_INTERRUPT_HANDLER(SIG_UART_TRANS) { UART* uart=s_uart[0]; uart->transmitComplete(); } void UART::transmitComplete(){ // indicate transmit complete, back to ready m_readyToTx = true; } // UART Receive Complete Interrupt Handler UART_INTERRUPT_HANDLER(SIG_UART_RECV) { // get received char uint8_t c = inb(UDR); UART* uart = s_uart[0]; uart->receiveComplete(c); } void UART::receiveComplete(uint8_t c){ // if there's a user function to handle this receive event if(m_rx_func) { // call it and pass the received data m_rx_func(c); } }