1818#include <avr/interrupt.h>
1919#include <avr/io.h>
2020#include <util/delay.h>
21- #include <util/setbaud.h>
2221
2322#include "core/sys.h"
2423#include "drivers/usart.h"
2928/* --------------------------------------------------- CONSTANTS ---------------------------------------------------- */
3029
3130#define usart_reg ( _idx ) \
32- { register_addr( UDR ## _idx ), \
33- register_addr( UCSR ## _idx ## A ), \
34- register_addr( UCSR ## _idx ## B ), \
35- register_addr( UCSR ## _idx ## C ), \
36- register_addr( UBRR ## _idx ## H ), \
37- register_addr( UBRR ## _idx ## L ) }
31+ { register8_addr( UDR ## _idx ), \
32+ register8_addr( UCSR ## _idx ## A ), \
33+ register8_addr( UCSR ## _idx ## B ), \
34+ register8_addr( UCSR ## _idx ## C ), \
35+ register16_addr( UBRR ## _idx ), \
36+ register8_addr( UBRR ## _idx ## H ), \
37+ register8_addr( UBRR ## _idx ## L ) }
3838
3939static struct
4040{
41- register_t udr ; /**< The UDRn register for this USART. */
42- register_t ucsra ; /**< The UCSRnA register for this USART. */
43- register_t ucsrb ; /**< The UCSRnB register for this USART. */
44- register_t ucsrc ; /**< The UCSRnC register for this USART. */
45- register_t ubrrh ; /**< The UBRRnH register for this USART. */
46- register_t ubrrl ; /**< The UBRRnL register for this USART. */
41+ register8_t udr ; /**< The UDRn register for this USART. */
42+ register8_t ucsra ; /**< The UCSRnA register for this USART. */
43+ register8_t ucsrb ; /**< The UCSRnB register for this USART. */
44+ register8_t ucsrc ; /**< The UCSRnC register for this USART. */
45+ register16_t ubrr ; /**< The UBRRn register for this USART. */
46+ register8_t ubrrh ; /**< The UBRRnH register for this USART. */
47+ register8_t ubrrl ; /**< The UBRRnL register for this USART. */
4748}
4849const s_reg_tbl [] =
4950{
@@ -69,14 +70,17 @@ _Static_assert( array_count( s_reg_tbl ) == USART_COUNT, "Invalid register table
6970/**
7071 * @def TX_DELAY_US
7172 * @brief The time to wait before trying again if the TX buffer is full, in microseconds.
73+ * @note This macro uses `19200` as a conservative estimated baud rate.
7274 */
73- #define TX_DELAY_US ( ( ( USEC_PER_MSEC * MSEC_PER_SEC ) / ( unsigned int )BAUD ) * 2 )
75+ #define TX_DELAY_US ( ( ( USEC_PER_MSEC * MSEC_PER_SEC ) / ( unsigned int )19200 ) * BITS_PER_BYTE )
7476
7577/* ----------------------------------------------------- MACROS ----------------------------------------------------- */
7678
7779// Validation macros
7880#define validate_usart ( _usart ) \
7981 assert_always( ( _usart ) < USART_COUNT )
82+ #define validate_baud ( _baud ) \
83+ assert_always( ( _baud ) < USART_BAUD_COUNT )
8084#define validate_data_bits ( _data_bits ) \
8185 assert_always( ( _data_bits ) < USART_DATA_BITS_COUNT )
8286#define validate_parity ( _parity ) \
@@ -95,6 +99,8 @@ _Static_assert( array_count( s_reg_tbl ) == USART_COUNT, "Invalid register table
9599 ( * ( s_reg_tbl[ ( _usart ) ].ucsrb ) )
96100#define UCSRC ( _usart ) \
97101 ( * ( s_reg_tbl[ ( _usart ) ].ucsrc ) )
102+ #define UBRR ( _usart ) \
103+ ( * ( s_reg_tbl[ ( _usart ) ].ubrr ) )
98104#define UBRRH ( _usart ) \
99105 ( * ( s_reg_tbl[ ( _usart ) ].ubrrh ) )
100106#define UBRRL ( _usart ) \
@@ -149,12 +155,6 @@ static volatile size_t s_tx_tail[ USART_COUNT ];
149155
150156/* ---------------------------------------------- PROCEDURE PROTOTYPES ---------------------------------------------- */
151157
152- /**
153- * @fn autoconfigure_baud( usart_t )
154- * @brief Automatically configures the baud rate for the specified USART based on the `BAUD` macro.
155- */
156- static void autoconfigure_baud ( usart_t usart );
157-
158158/**
159159 * @fn isr_rx_complete( usart_t )
160160 * @brief Runs the USART RX complete interrupt service routine for the specified USART.
@@ -185,6 +185,12 @@ static size_t rx_buf_avail( usart_t usart );
185185 */
186186static size_t rx_buf_count ( usart_t usart );
187187
188+ /**
189+ * @fn set_baud( usart_t, usart_baud_t )
190+ * @brief Sets the baud rate for the specified USART.
191+ */
192+ static void set_baud ( usart_t usart , usart_baud_t baud );
193+
188194/**
189195 * @fn set_data_bits( usart_t, usart_data_bits_t )
190196 * @brief Sets the data bits setting for the specified USART.
@@ -314,11 +320,13 @@ usart_error_t usart_get_errors( usart_t usart )
314320void usart_init ( usart_t usart ,
315321 bool rx_enabled ,
316322 bool tx_enabled ,
323+ usart_baud_t baud ,
317324 usart_data_bits_t data_bits ,
318325 usart_stop_bits_t stop_bits ,
319326 usart_parity_t parity )
320327{
321328 validate_usart ( usart );
329+ validate_baud ( baud );
322330 validate_data_bits ( data_bits );
323331 validate_stop_bits ( stop_bits );
324332 validate_parity ( parity );
@@ -332,7 +340,7 @@ void usart_init( usart_t usart,
332340 TX_TAIL ( usart ) = 0 ;
333341
334342 // Configure USART
335- autoconfigure_baud ( usart );
343+ set_baud ( usart , baud );
336344 set_data_bits ( usart , data_bits );
337345 set_stop_bits ( usart , stop_bits );
338346 set_parity ( usart , parity );
@@ -347,20 +355,6 @@ void usart_init( usart_t usart,
347355} /* usart_init() */
348356
349357
350- size_t usart_max_rx_size ( void )
351- {
352- return ( RX_BUF_SIZE );
353-
354- } /* usart_max_rx_size() */
355-
356-
357- size_t usart_max_tx_size ( void )
358- {
359- return ( TX_BUF_SIZE );
360-
361- } /* usart_max_tx_size() */
362-
363-
364358size_t usart_rx ( usart_t usart , byte_t * data , size_t max_size )
365359{
366360 validate_usart ( usart );
@@ -449,19 +443,6 @@ size_t usart_tx_str( usart_t usart, char const * str, usart_wait_mode_t wait_mod
449443} /* usart_tx_str() */
450444
451445
452- static void autoconfigure_baud ( usart_t usart )
453- {
454- UBRRH ( usart ) = UBRRH_VALUE ;
455- UBRRL ( usart ) = UBRRL_VALUE ;
456- #if ( USE_2X )
457- set_bit ( UCSRA ( usart ), U2X0 );
458- #else
459- clear_bit ( UCSRA ( usart ), U2X0 );
460- #endif
461-
462- } /* autoconfigure_baud() */
463-
464-
465446static void isr_rx_complete ( usart_t usart , event_t event )
466447{
467448 // If the buffer is full, drop the oldest received byte
@@ -523,6 +504,70 @@ static size_t rx_buf_count( usart_t usart )
523504} /* rx_buf_count() */
524505
525506
507+ static void set_baud ( usart_t usart , usart_baud_t baud )
508+ {
509+ _Static_assert ( F_CPU == 16000000UL , "Baud settings depend on F_CPU of 16 MHz!" );
510+
511+ // Always enable 2X setting
512+ set_bit ( UCSRA ( usart ), U2X0 );
513+
514+ // Set UBRR register based on selected baud rate
515+ // These are taken from table 19-12 in the ATmega1283P data sheet:
516+ // https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega164A_PA-324A_PA-644A_PA-1284_P_Data-Sheet-40002070B.pdf
517+ switch ( baud )
518+ {
519+ case USART_BAUD_2400 :
520+ UBRR ( usart ) = 832 ;
521+ break ;
522+
523+ case USART_BAUD_4800 :
524+ UBRR ( usart ) = 416 ;
525+ break ;
526+
527+ case USART_BAUD_9600 :
528+ UBRR ( usart ) = 207 ;
529+ break ;
530+
531+ case USART_BAUD_14400 :
532+ UBRR ( usart ) = 138 ;
533+ break ;
534+
535+ case USART_BAUD_19200 :
536+ UBRR ( usart ) = 103 ;
537+ break ;
538+
539+ case USART_BAUD_28800_NOT_RECOMMENDED :
540+ UBRR ( usart ) = 68 ;
541+ break ;
542+
543+ case USART_BAUD_38400 :
544+ UBRR ( usart ) = 51 ;
545+ break ;
546+
547+ case USART_BAUD_57600_NOT_RECOMMENDED :
548+ UBRR ( usart ) = 34 ;
549+ break ;
550+
551+ case USART_BAUD_76800 :
552+ UBRR ( usart ) = 25 ;
553+ break ;
554+
555+ case USART_BAUD_115200_NOT_RECOMMENDED :
556+ UBRR ( usart ) = 16 ;
557+ break ;
558+
559+ case USART_BAUD_230400_NOT_RECOMMENDED :
560+ UBRR ( usart ) = 8 ;
561+ break ;
562+
563+ case USART_BAUD_250000 :
564+ UBRR ( usart ) = 7 ;
565+ break ;
566+ }
567+
568+ } /* set_baud() */
569+
570+
526571static void set_data_bits ( usart_t usart , usart_data_bits_t data_bits )
527572{
528573 // Note that UCSZn2 is in UCSRnB, not UCSRnC
0 commit comments