/*
* UART . c
*
* Created : 25 / 11 / 2021 16 : 26 : 10
* Author : n0x
*/
# include "UART.h"
/* create structs for TX and TX buffer */
CircularBuffer TxBuffer ;
CircularBuffer * pTxBuffer = & TxBuffer ;
CircularBuffer RxBuffer ;
CircularBuffer * pRxBuffer = & RxBuffer ;
volatile uint8_t TxActive ;
void
uart_init ( void ) {
UBRR0 = 103 ; /* set BAUD rate to 9600 */
UCSR0C | =
( 0 < < UMSEL00 ) | ( 0 < < UMSEL01 ) | /* Async UART */
( 0 < < UPM00 ) | ( 0 < < UPM01 ) | /* Disable Parity */
( 1 < < UCSZ00 ) | ( 1 < < UCSZ01 ) | /* 8 Bit */
( 0 < < USBS0 ) ; /* 1 Stopbit */
UCSR0B | =
( 1 < < TXEN0 ) | ( 1 < < RXEN0 ) | /* enable send and receive */
( 1 < < RXCIE0 ) ; /* enable Receive interrupts */
/* Initiate read- and write-pointers with 0 */
pTxBuffer - > Readpointer = 0 ;
pTxBuffer - > Writepointer = 0 ;
pRxBuffer - > Readpointer = 0 ;
pRxBuffer - > Writepointer = 0 ;
}
/********Sending Data********/
void
uart_send_string ( char * string ) {
/* Take a whole string and transmit every char from it */
int i = 0 ;
while ( string [ i ] ! = ' \0 ' ) {
uart_send_byte ( string [ i ] ) ;
i + + ;
}
}
void
uart_send_byte ( char c ) {
/* Disable the TX Interrupt to prevent issues while writing to the send buffer*/
UCSR0B & = ~ ( 1 < < TXCIE0 ) ;
/* Check if a transmit is in progress
if yes - > write the byte to the buffer
if no - > write the byte to the UDR0 register and enable the transmit in progress flag
*/
if ( TxActive ) {
pTxBuffer - > data [ pTxBuffer - > Writepointer + + ] = c ;
if ( pTxBuffer - > Writepointer > = SIZE_BUFFER ) {
pTxBuffer - > Writepointer = 0 ;
}
} else {
TxActive = 1 ;
UDR0 = c ;
}
/* Enable the TX Interrupt again*/
UCSR0B | = ( 1 < < TXCIE0 ) ;
}
/* when data (a data frame) is to be send (written to UDR0) */
ISR ( USART0_TX_vect ) {
/* check if the read and write pointer of the send buffer are not aligned
if not aligned - > read the next byte and write it to UDR0 register
if aligned - > no more data to send , disable the send in progress flag */
if ( pTxBuffer - > Readpointer ! = pTxBuffer - > Writepointer )
{
/* writing data to the register withing the interrupt will cause a new interrupt which then will repeat till no more data is to be read from the send buffer */
UDR0 = pTxBuffer - > data [ pTxBuffer - > Readpointer + + ] ;
if ( pTxBuffer - > Readpointer > = SIZE_BUFFER ) {
pTxBuffer - > Readpointer = 0 ;
}
} else {
TxActive = 0 ;
}
}
/*******Receiving Data*******/
uint8_t
uart_data_available ( void ) {
uint8_t dataAvailabel = 0 ;
/* Disable the RX Interrupt to prevent issues when checking if data is available */
UCSR0B & = ~ ( 1 < < RXCIE0 ) ;
/* check if read and write pointer are at different locations
if yes - > data is available and can be read */
if ( pRxBuffer - > Readpointer ! = pRxBuffer - > Writepointer ) {
dataAvailabel = 1 ;
}
/* Enable the RX Interrupt again*/
UCSR0B | = ( 1 < < RXCIE0 ) ;
return dataAvailabel ;
}
char
uart_get_data ( void ) {
char data = 0 ;
/* Disable the RX Interrupt to prevent issues when reading out a char from the buffer */
UCSR0B & = ~ ( 1 < < RXCIE0 ) ;
/* check if read and write pointer are at different locations
if yes - > data is available and can be read */
if ( pRxBuffer - > Readpointer ! = pRxBuffer - > Writepointer )
{
/* read a char from the buffer and increment the read pointer */
data = pRxBuffer - > data [ pRxBuffer - > Readpointer + + ] ;
if ( pRxBuffer - > Readpointer > = SIZE_BUFFER ) {
pRxBuffer - > Readpointer = 0 ;
}
}
/* Enable the RX Interrupt again*/
UCSR0B | = ( 1 < < RXCIE0 ) ;
/* give back the read in character */
return data ;
}
/* when data (a data frame) is received */
ISR ( USART0_RX_vect ) {
uint8_t status = UCSR0A ;
uint8_t data = UDR0 ;
/* check status flags if data is correctly accessible */
if ( ( status & ( ( 1 < < DOR0 ) | ( 1 < < FE0 ) ) ) = = 0 ) {
/* Save data to buffer and increment the write pointer */
pRxBuffer - > data [ pRxBuffer - > Writepointer + + ] = data ;
if ( pRxBuffer - > Writepointer > = SIZE_BUFFER ) {
pRxBuffer - > Writepointer = 0 ;
}
}
}