/*! * \brief * * \author Jan Oleksiewicz * \license SPDX-License-Identifier: MIT */ #include #include #include #include #include #include #include #include "usart.h" #ifndef NO_TX0_INTERRUPT volatile uint8_t tx0_Tail, tx0_Head; char tx0_buffer[TX0_BUFFER_SIZE] __attribute__ ((used)); #endif #ifndef NO_RX0_INTERRUPT volatile uint8_t rx0_Tail, rx0_Head; char rx0_buffer[RX0_BUFFER_SIZE] __attribute__ ((used)); #endif #ifndef NO_TX1_INTERRUPT volatile uint8_t tx1_Tail, tx1_Head; char tx1_buffer[TX1_BUFFER_SIZE] __attribute__ ((used)); #endif #ifndef NO_RX1_INTERRUPT volatile uint8_t rx1_Tail, rx1_Head; char rx1_buffer[RX1_BUFFER_SIZE] __attribute__ ((used)); #endif #ifndef NO_TX2_INTERRUPT volatile uint8_t tx2_Tail, tx2_Head; char tx2_buffer[TX2_BUFFER_SIZE] __attribute__ ((used)); #endif #ifndef NO_RX2_INTERRUPT volatile uint8_t rx2_Tail, rx2_Head; char rx2_buffer[RX2_BUFFER_SIZE] __attribute__ ((used)); #endif #ifndef NO_TX3_INTERRUPT volatile uint8_t tx3_Tail, tx3_Head; char tx3_buffer[TX3_BUFFER_SIZE] __attribute__ ((used)); #endif #ifndef NO_RX3_INTERRUPT volatile uint8_t rx3_Tail, rx3_Head; char rx3_buffer[RX3_BUFFER_SIZE] __attribute__ ((used)); #endif #ifdef USART_NO_LOCAL_BUFFERS extern char u_tmp_buff[]; #endif #ifdef USE_USART0 /* void uart_init(uint16_t ubrr_value) { #ifdef USART0_RS485_MODE RS485_CONTROL0_DDR |= (1<>8); #ifdef USART0_U2X_SPEED #ifdef USART0_MPCM_MODE UCSR0A_REGISTER = (1<>8); #ifdef USART0_U2X_SPEED #ifdef USART0_MPCM_MODE UCSR0A_REGISTER = (1<>8); #ifdef USART1_U2X_SPEED #ifdef USART1_MPCM_MODE UCSR1A_REGISTER = (1<>8); #ifdef USART2_U2X_SPEED #ifdef USART2_MPCM_MODE UCSR2A_REGISTER = (1<>8); #ifdef USART3_U2X_SPEED #ifdef USART3_MPCM_MODE UCSR3A_REGISTER = (1<> 4) & 0x0f; #ifdef USART_PUTHEX_IN_UPPERCASE uart0_putc( (tmp <= 9 ? '0' + tmp : 'A' - 10 + tmp)); #else uart0_putc( (tmp <= 9 ? '0' + tmp : 'a' - 10 + tmp)); #endif tmp = data & 0x0f; #ifdef USART_PUTHEX_IN_UPPERCASE uart0_putc( (tmp <= 9 ? '0' + tmp : 'A' - 10 + tmp)); #else uart0_putc( (tmp <= 9 ? '0' + tmp : 'a' - 10 + tmp)); #endif } //****************************************************************** //Function : Send long integer formated into ASCI string (base 10). //Arguments : int32_t data value. //Return : none //****************************************************************** void uart0_putlong(int32_t data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[12]; // heading, 10 digit bytes, NULL #endif ltoa(data, u_tmp_buff, 10); uart0_putstr(u_tmp_buff); } //****************************************************************** //Function : Send long integer formated into ASCI string. //Arguments : 1. int32_t data value. // : 2. Base value (DEC, HEX, OCT, BIN, etc.). //Return : none //****************************************************************** void uart0_putlongr(int32_t data, uint8_t radix) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[17]; // heading, 15 digit bytes, NULL #endif ltoa(data, u_tmp_buff, radix); uart0_putstr(u_tmp_buff); } //****************************************************************** //Function : Send unsigned long integer formated into ASCI string (base 10). //Arguments : uint32_t data value. //Return : none //****************************************************************** void uart0_putulong(uint32_t data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[12]; // heading, 10 digit bytes, NULL #endif ultoa(data, u_tmp_buff, 10); uart0_putstr(u_tmp_buff); } //****************************************************************** //Function : Send unsigned long integer formated into ASCI string. //Arguments : 1. uint32_t data value. // : 2. Base value (DEC, HEX, OCT, BIN, etc.). //Return : none //****************************************************************** void uart0_putulongr(uint32_t data, uint8_t radix) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[17]; // heading, 15 digit bytes, NULL #endif ultoa(data, u_tmp_buff, radix); uart0_putstr(u_tmp_buff); } //****************************************************************** //Function : Send floating point value formated into ASCI string. //Arguments : float data value. //Return : none //****************************************************************** void uart0_putfloat(float data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[16]; #endif dtostrf(data, 15, 6, u_tmp_buff); char *p = u_tmp_buff; while(*p == ' ') // remove all unwanted spaces p++; uart0_putstr(p); } //****************************************************************** //Function : Send floating point integer formated into ASCI string. //Arguments : 1. Float data value. // : 2. Number of displayed digits after the dot. //Return : none //****************************************************************** void uart0_fputfloat(float data, uint8_t precision) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[16]; #endif dtostrf(data, 15, precision, u_tmp_buff); char *p = u_tmp_buff; while(*p == ' ') // remove all unwanted spaces p++; uart0_putstr(p); } //****************************************************************** //Function : Wait until all data in TX buffer are flushed. //Arguments : none //Return : none //****************************************************************** void uart0_flush(void) { #ifdef USART0_RS485_MODE // flush UDR buffer while (RS485_CONTROL0_PORT & (1<> 4) & 0x0f; #ifdef USART_PUTHEX_IN_UPPERCASE uart1_putc( (tmp <= 9 ? '0' + tmp : 'A' - 10 + tmp)); #else uart1_putc( (tmp <= 9 ? '0' + tmp : 'a' - 10 + tmp)); #endif tmp = data & 0x0f; #ifdef USART_PUTHEX_IN_UPPERCASE uart1_putc( (tmp <= 9 ? '0' + tmp : 'A' - 10 + tmp)); #else uart1_putc( (tmp <= 9 ? '0' + tmp : 'a' - 10 + tmp)); #endif } void uart1_putlong(int32_t data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[12]; // heading, 10 digit bytes, NULL #endif ltoa(data, u_tmp_buff, 10); uart1_putstr(u_tmp_buff); } void uart1_putlongr(int32_t data, uint8_t radix) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[17]; // heading, 15 digit bytes, NULL #endif ltoa(data, u_tmp_buff, radix); uart1_putstr(u_tmp_buff); } void uart1_putulong(uint32_t data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[12]; // heading, 10 digit bytes, NULL #endif ultoa(data, u_tmp_buff, 10); uart1_putstr(u_tmp_buff); } void uart1_putulongr(uint32_t data, uint8_t radix) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[17]; // heading, 15 digit bytes, NULL #endif ultoa(data, u_tmp_buff, radix); uart1_putstr(u_tmp_buff); } void uart1_putfloat(float data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[16]; #endif dtostrf(data, 15, 6, u_tmp_buff); char *p = u_tmp_buff; while(*p == ' ') // remove all unwanted spaces p++; uart1_putstr(p); } void uart1_fputfloat(float data, uint8_t precision) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[16]; #endif dtostrf(data, 15, precision, u_tmp_buff); char *p = u_tmp_buff; while(*p == ' ') // remove all unwanted spaces p++; uart1_putstr(p); } void uart1_flush(void) { #ifdef USART1_RS485_MODE // flush UDR buffer while (RS485_CONTROL1_PORT & (1<> 4) & 0x0f; #ifdef USART_PUTHEX_IN_UPPERCASE uart2_putc( (tmp <= 9 ? '0' + tmp : 'A' - 10 + tmp)); #else uart2_putc( (tmp <= 9 ? '0' + tmp : 'a' - 10 + tmp)); #endif tmp = data & 0x0f; #ifdef USART_PUTHEX_IN_UPPERCASE uart2_putc( (tmp <= 9 ? '0' + tmp : 'A' - 10 + tmp)); #else uart2_putc( (tmp <= 9 ? '0' + tmp : 'a' - 10 + tmp)); #endif } void uart2_putlong(int32_t data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[12]; // heading, 10 digit bytes, NULL #endif ltoa(data, u_tmp_buff, 10); uart2_putstr(u_tmp_buff); } void uart2_putlongr(int32_t data, uint8_t radix) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[17]; // heading, 15 digit bytes, NULL #endif ltoa(data, u_tmp_buff, radix); uart2_putstr(u_tmp_buff); } void uart2_putulong(uint32_t data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[12]; // heading, 10 digit bytes, NULL #endif ultoa(data, u_tmp_buff, 10); uart2_putstr(u_tmp_buff); } void uart2_putulongr(uint32_t data, uint8_t radix) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[17]; // heading, 15 digit bytes, NULL #endif ultoa(data, u_tmp_buff, radix); uart2_putstr(u_tmp_buff); } void uart2_putfloat(float data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[16]; #endif dtostrf(data, 15, 6, u_tmp_buff); char *p = u_tmp_buff; while(*p == ' ') // remove all unwanted spaces p++; uart2_putstr(p); } void uart2_fputfloat(float data, uint8_t precision) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[16]; #endif dtostrf(data, 15, precision, u_tmp_buff); char *p = u_tmp_buff; while(*p == ' ') // remove all unwanted spaces p++; uart2_putstr(p); } void uart2_flush(void) { #ifdef USART2_RS485_MODE // flush UDR buffer while (RS485_CONTROL2_PORT & (1<> 4) & 0x0f; #ifdef USART_PUTHEX_IN_UPPERCASE uart3_putc( (tmp <= 9 ? '0' + tmp : 'A' - 10 + tmp)); #else uart3_putc( (tmp <= 9 ? '0' + tmp : 'a' - 10 + tmp)); #endif tmp = data & 0x0f; #ifdef USART_PUTHEX_IN_UPPERCASE uart3_putc( (tmp <= 9 ? '0' + tmp : 'A' - 10 + tmp)); #else uart3_putc( (tmp <= 9 ? '0' + tmp : 'a' - 10 + tmp)); #endif } void uart3_putlong(int32_t data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[12]; // heading, 10 digit bytes, NULL #endif ltoa(data, u_tmp_buff, 10); uart3_putstr(u_tmp_buff); } void uart3_putlongr(int32_t data, uint8_t radix) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[17]; // heading, 15 digit bytes, NULL #endif ltoa(data, u_tmp_buff, radix); uart3_putstr(u_tmp_buff); } void uart3_putulong(uint32_t data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[12]; // heading, 10 digit bytes, NULL #endif ultoa(data, u_tmp_buff, 10); uart3_putstr(u_tmp_buff); } void uart3_putulongr(uint32_t data, uint8_t radix) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[17]; // heading, 15 digit bytes, NULL #endif ultoa(data, u_tmp_buff, radix); uart3_putstr(u_tmp_buff); } void uart3_putfloat(float data) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[16]; #endif dtostrf(data, 15, 6, u_tmp_buff); char *p = u_tmp_buff; while(*p == ' ') // remove all unwanted spaces p++; uart3_putstr(p); } void uart3_fputfloat(float data, uint8_t precision) { #ifndef USART_NO_LOCAL_BUFFERS char u_tmp_buff[16]; #endif dtostrf(data, 15, precision, u_tmp_buff); char *p = u_tmp_buff; while(*p == ' ') // remove all unwanted spaces p++; uart3_putstr(p); } void uart3_flush(void) { #ifdef USART3_RS485_MODE // flush UDR buffer while (RS485_CONTROL3_PORT & (1<= 0) //****************************************************************** #ifdef USART_NO_ABI_BREAKING_PREMATURES int16_t uart0_getData(void) { register uint8_t tmp_rx_Tail = rx0_Tail; uint8_t tmp; if(tmp_rx_Tail == rx0_Head) return -1; tmp_rx_Tail = (tmp_rx_Tail+1) & RX0_BUFFER_MASK; tmp = rx0_buffer[tmp_rx_Tail]; rx0_Tail = tmp_rx_Tail; #ifdef USART0_EXTEND_RX_BUFFER UCSR0B_REGISTER |= (1< udata) { default: #ifndef NO_TX0_INTERRUPT case 0: if (data == '\n') uart0_putc('\r'); uart0_putc(data); break; #endif #ifndef NO_TX1_INTERRUPT case 1: if (data == '\n') uart1_putc('\r'); uart1_putc(data); break; #endif #ifndef NO_TX2_INTERRUPT case 2: if (data == '\n') uart2_putc('\r'); uart2_putc(data); break; #endif #ifndef NO_TX3_INTERRUPT case 3: if (data == '\n') uart3_putc('\r'); uart3_putc(data); break; #endif } return 0; } #endif // NO_USART_TX #ifndef NO_USART_RX int uart_getchar(FILE *stream) { int16_t tmp; switch((uint16_t) stream -> udata) { default: #ifndef NO_RX0_INTERRUPT case 0: while ( (tmp = uart0_getData()) < 0 ); #ifdef RX_STDIO_GETCHAR_ECHO tmp = uart0_putc_((uint8_t)tmp); #endif break; #endif #ifndef NO_RX1_INTERRUPT case 1: while ( (tmp = uart1_getData()) < 0 ); #ifdef RX_STDIO_GETCHAR_ECHO tmp = uart1_putc_((uint8_t)tmp); #endif break; #endif #ifndef NO_RX2_INTERRUPT case 2: while ( (tmp = uart2_getData()) < 0 ); #ifdef RX_STDIO_GETCHAR_ECHO tmp = uart2_putc_((uint8_t)tmp); #endif break; #endif #ifndef NO_RX3_INTERRUPT case 3: while ( (tmp = uart3_getData()) < 0 ); #ifdef RX_STDIO_GETCHAR_ECHO tmp = uart3_putc_((uint8_t)tmp); #endif break; #endif } return (uint8_t)tmp; } #endif // NO_USART_RX #ifdef USE_USART0 #if defined(NO_RX0_INTERRUPT) FILE uart0_out = FDEV_SETUP_STREAM_U(uart_putchar, NULL, _FDEV_SETUP_WRITE, (void*)0); #elif defined(NO_TX0_INTERRUPT) FILE uart0_in = FDEV_SETUP_STREAM_U(NULL, uart_getchar, _FDEV_SETUP_READ, (void*)0); #else FILE uart0_io = FDEV_SETUP_STREAM_U(uart_putchar, uart_getchar, _FDEV_SETUP_RW, (void*)0); FILE uart0_in = FDEV_SETUP_STREAM_U(NULL, uart_getchar, _FDEV_SETUP_READ, (void*)0); FILE uart0_out = FDEV_SETUP_STREAM_U(uart_putchar, NULL, _FDEV_SETUP_WRITE, (void*)0); #endif #endif // USE_USART0 #ifdef USE_USART1 #if defined(NO_RX1_INTERRUPT) FILE uart1_out = FDEV_SETUP_STREAM_U(uart_putchar, NULL, _FDEV_SETUP_WRITE, (void*)1); #elif defined(NO_TX1_INTERRUPT) FILE uart1_in = FDEV_SETUP_STREAM_U(NULL, uart_getchar, _FDEV_SETUP_READ, (void*)1); #else FILE uart1_io = FDEV_SETUP_STREAM_U(uart_putchar, uart_getchar, _FDEV_SETUP_RW, (void*)1); FILE uart1_in = FDEV_SETUP_STREAM_U(NULL, uart_getchar, _FDEV_SETUP_READ, (void*)1); FILE uart1_out = FDEV_SETUP_STREAM_U(uart_putchar, NULL, _FDEV_SETUP_WRITE, (void*)1); #endif #endif // USE_USART1 #ifdef USE_USART2 #if defined(NO_RX2_INTERRUPT) FILE uart2_out = FDEV_SETUP_STREAM_U(uart_putchar, NULL, _FDEV_SETUP_WRITE, (void*)2); #elif defined(NO_TX2_INTERRUPT) FILE uart2_in = FDEV_SETUP_STREAM_U(NULL, uart_getchar, _FDEV_SETUP_READ, (void*)2); #else FILE uart2_io = FDEV_SETUP_STREAM_U(uart_putchar, uart_getchar, _FDEV_SETUP_RW, (void*)2); FILE uart2_in = FDEV_SETUP_STREAM_U(NULL, uart_getchar, _FDEV_SETUP_READ, (void*)2); FILE uart2_out = FDEV_SETUP_STREAM_U(uart_putchar, NULL, _FDEV_SETUP_WRITE, (void*)2); #endif #endif // USE_USART2 #ifdef USE_USART3 #if defined(NO_RX3_INTERRUPT) FILE uart3_out = FDEV_SETUP_STREAM_U(uart_putchar, NULL, _FDEV_SETUP_WRITE, (void*)3); #elif defined(NO_TX3_INTERRUPT) FILE uart3_in = FDEV_SETUP_STREAM_U(NULL, uart_getchar, _FDEV_SETUP_READ, (void*)3); #else FILE uart3_io = FDEV_SETUP_STREAM_U(uart_putchar, uart_getchar, _FDEV_SETUP_RW, (void*)3); FILE uart3_in = FDEV_SETUP_STREAM_U(NULL, uart_getchar, _FDEV_SETUP_READ, (void*)3); FILE uart3_out = FDEV_SETUP_STREAM_U(uart_putchar, NULL, _FDEV_SETUP_WRITE, (void*)3); #endif #endif // USE_USART3 #else // single USART mcu #ifndef NO_TX0_INTERRUPT int uart_putchar(char data, FILE *stream) { if (data == '\n') uart0_putc('\r'); uart_putc(data); return 0; } #endif // NO_TX0_INTERRUPT #ifndef NO_RX0_INTERRUPT int uart_getchar(FILE *stream) { int16_t tmp; while ( (tmp = uart0_getData()) < 0 ); #ifdef RX_STDIO_GETCHAR_ECHO tmp = uart0_putc_((uint8_t)tmp); #endif return (uint8_t)tmp; } #endif //NO_RX0_INTERRUPT #if defined(NO_RX0_INTERRUPT) FILE uart0_out = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); #elif defined(NO_TX0_INTERRUPT) FILE uart0_in = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ); #else FILE uart0_io = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); FILE uart0_in = FDEV_SETUP_STREAM(NULL, uart_getchar, _FDEV_SETUP_READ); FILE uart0_out = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); #endif #endif // single/multi USART //****************************************************************** //ISR prototypes //****************************************************************** /* ISR(TXn_INTERRUPT) // do it in a little weird way { register uint8_t tmp_tx_Tail = (txn_Tail + 1) & TXn_BUFFER_MASK; if(tmp_tx_Tail == txn_Head) UCSRnB_REGISTER &= ~(1<