OpenModem/hardware/Serial.c

357 lines
8.3 KiB
C
Raw Permalink Normal View History

2014-12-02 17:10:06 -07:00
#include "Serial.h"
#include <stdio.h>
#include <string.h>
#include "util/Config.h"
2014-12-02 17:10:06 -07:00
2019-01-29 12:43:46 -07:00
extern volatile uint8_t queue_height;
2014-12-02 17:10:06 -07:00
void serial_init(Serial *serial) {
memset(serial, 0, sizeof(*serial));
2019-02-04 09:02:19 -07:00
memset(uart0Buf, 0, sizeof(uart0Buf));
memset(uart1Buf, 0, sizeof(uart1Buf));
2019-02-04 09:02:19 -07:00
serial_setbaudrate_115200(0);
serial_setbaudrate_115200(1);
2014-12-02 17:10:06 -07:00
2019-01-08 12:56:58 -07:00
// Set to 8-bit data, enable RX and TX, enable receive interrupt
2014-12-02 17:10:06 -07:00
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
2019-01-08 12:56:58 -07:00
UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0);
2014-12-02 17:10:06 -07:00
2019-02-04 09:02:19 -07:00
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10);
UCSR1B = _BV(RXEN1) | _BV(TXEN1) | _BV(RXCIE1);
2014-12-02 17:10:06 -07:00
FILE uart0_fd = FDEV_SETUP_STREAM(uart0_putchar, uart0_getchar, _FDEV_SETUP_RW);
2019-02-04 09:02:19 -07:00
FILE uart1_fd = FDEV_SETUP_STREAM(uart1_putchar, uart1_getchar, _FDEV_SETUP_RW);
2019-01-08 05:19:58 -07:00
2014-12-02 17:10:06 -07:00
serial->uart0 = uart0_fd;
2019-02-04 09:02:19 -07:00
serial->uart1 = uart1_fd;
2019-01-08 12:56:58 -07:00
2020-06-01 05:45:26 -06:00
fifo_init(&uart0FIFO, uart0Buf, CONFIG_UART0_BUFFER_SIZE);
fifo_init(&uart1FIFO, uart1Buf, CONFIG_UART1_BUFFER_SIZE);
2014-12-02 17:10:06 -07:00
}
bool serial_available(uint8_t index) {
if (index == 0) {
if (UCSR0A & _BV(RXC0)) return true;
2019-02-04 09:02:19 -07:00
} else if (index == 1) {
if (UCSR1A & _BV(RXC1)) return true;
2014-12-02 17:10:06 -07:00
}
2019-02-04 09:02:19 -07:00
2014-12-02 17:10:06 -07:00
return false;
}
int uart0_putchar(char c, FILE *stream) {
2019-01-12 07:12:51 -07:00
LED_COM_ON();
2014-12-02 17:10:06 -07:00
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
return 1;
2014-12-02 17:10:06 -07:00
}
int uart0_getchar(FILE *stream) {
2014-12-02 17:10:06 -07:00
loop_until_bit_is_set(UCSR0A, RXC0);
2019-02-04 09:02:19 -07:00
LED_COM_ON();
2014-12-02 17:10:06 -07:00
return UDR0;
}
char uart0_getchar_nowait(void) {
if (!(UCSR0A & _BV(RXC0))) return EOF;
2019-02-04 09:02:19 -07:00
LED_COM_ON();
2014-12-02 17:10:06 -07:00
return UDR0;
2019-01-08 12:56:58 -07:00
}
2019-02-04 09:02:19 -07:00
int uart1_putchar(char c, FILE *stream) {
loop_until_bit_is_set(UCSR1A, UDRE1);
UDR1 = c;
return 1;
}
int uart1_getchar(FILE *stream) {
loop_until_bit_is_set(UCSR1A, RXC1);
return UDR1;
}
char uart1_getchar_nowait(void) {
if (!(UCSR1A & _BV(RXC1))) return EOF;
return UDR1;
}
2019-01-08 12:56:58 -07:00
ISR(USART0_RX_vect) {
if (serial_available(0)) {
2019-01-12 07:12:51 -07:00
LED_COM_ON();
2019-02-04 09:02:19 -07:00
if (!fifo_isfull(&uart0FIFO)) {
2019-01-29 12:43:46 -07:00
char c = uart0_getchar_nowait();
2020-06-01 05:46:26 -06:00
fifo_push(&uart0FIFO, c);
2019-11-08 08:36:01 -07:00
} else {
2020-06-01 13:27:38 -06:00
uart0_getchar_nowait();
2019-01-29 12:43:46 -07:00
}
2019-01-08 12:56:58 -07:00
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
ISR(USART1_RX_vect) {
if (serial_available(1)) {
if (!fifo_isfull(&uart1FIFO)) {
char c = uart1_getchar_nowait();
fifo_push(&uart1FIFO, c);
2019-11-08 08:36:01 -07:00
} else {
2020-06-01 13:27:38 -06:00
uart1_getchar_nowait();
2019-02-04 09:02:19 -07:00
}
}
}
void serial_setbaudrate_1200(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 1200
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_2400(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 2400
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_4800(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 4800
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_9600(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 9600
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_14400(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 14400
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_19200(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 19200
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_28800(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 28800
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_38400(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 38400
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_57600(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 57600
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_76800(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 76800
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_115200(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 115200
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}
2019-02-04 09:02:19 -07:00
void serial_setbaudrate_230400(uint8_t port) {
2019-01-29 08:41:27 -07:00
#undef BAUD
#define BAUD 230400
#include <util/setbaud.h>
2019-02-04 09:02:19 -07:00
if (port == 0) {
UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif
} else if (port == 1) {
UBRR1H = UBRRH_VALUE; UBRR1L = UBRRL_VALUE;
#if USE_2X
UCSR1A |= _BV(U2X0);
#else
UCSR1A &= ~(_BV(U2X0));
#endif
}
2019-01-29 08:41:27 -07:00
}