Implement USART with bot RX and TX interrupts
This commit is contained in:
12
src/bus/twi.c
Normal file
12
src/bus/twi.c
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "bus/twi.h"
|
||||
#include <avr/io.h>
|
||||
|
||||
int TWI_Init(void)
|
||||
{
|
||||
// Set SCL bit rate to 400kHz
|
||||
|
||||
TWSR = 0x00; // TWI status register
|
||||
TWBR = 0x0C; // TWI bit rate register
|
||||
|
||||
return 0;
|
||||
}
|
||||
6
src/bus/twi.h
Normal file
6
src/bus/twi.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef MAD_CORE_BUS_TWI_H
|
||||
#define MAD_CORE_BUS_TWI_H
|
||||
|
||||
int TWI_Init(void);
|
||||
|
||||
#endif // MAD_CORE_BUS_TWI_H
|
||||
93
src/bus/usart.c
Normal file
93
src/bus/usart.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "common.h"
|
||||
#include "bus/usart.h"
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
//#include <util/atomic.h>
|
||||
|
||||
#define USART_BAUDRATE 9600
|
||||
#define USART_RXBUF_SIZE 512
|
||||
#define USART_TXBUF_SIZE 512
|
||||
|
||||
#define USART_RXBUF_MASK (USART_RXBUF_SIZE - 1)
|
||||
#define USART_TXBUF_MASK (USART_TXBUF_SIZE - 1)
|
||||
#define USART_BAUD_PRESCALE ((((F_CPU / 16) + \
|
||||
(USART_BAUDRATE / 2)) / (USART_BAUDRATE)) - 1)
|
||||
|
||||
static volatile char rxbuf[USART_RXBUF_SIZE]; // RX ring buffer
|
||||
static volatile char txbuf[USART_TXBUF_SIZE]; // TX ring buffer
|
||||
static volatile short rxhead, txhead; // Current write position
|
||||
static volatile short rxtail, txtail; // Current read position
|
||||
|
||||
int USART_Init(void)
|
||||
{
|
||||
rxhead = 0;
|
||||
rxtail = 0;
|
||||
txhead = 0;
|
||||
txtail = 0;
|
||||
|
||||
UCSRB = BIT(RXCIE); // Handle RXC interrupts
|
||||
UCSRB |= BIT(RXEN) | BIT(TXEN); // Enable RX and TX circuitry
|
||||
UCSRC = BIT(URSEL) | BIT(UCSZ0) | BIT(UCSZ1); // Using 8-bit chars
|
||||
UBRRH = (USART_BAUD_PRESCALE >> 8); // Set baud rate upper byte
|
||||
UBRRL = USART_BAUD_PRESCALE; // Set baud rate lower byte
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char USART_Getc(void)
|
||||
{
|
||||
if (rxhead == rxtail) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rxtail = (rxtail + 1) & USART_RXBUF_MASK;
|
||||
return rxbuf[rxtail];
|
||||
}
|
||||
|
||||
void USART_Putc(char ch)
|
||||
{
|
||||
short head;
|
||||
|
||||
head = (txhead + 1) & USART_TXBUF_MASK;
|
||||
while (head == txtail); // Wait for space
|
||||
|
||||
txbuf[head] = ch;
|
||||
txhead = head;
|
||||
|
||||
// Enable interrupt
|
||||
UCSRB |= BIT(UDRIE);
|
||||
}
|
||||
|
||||
// INT: Rx complete
|
||||
ISR(USART_RXC_vect)
|
||||
{
|
||||
short head;
|
||||
|
||||
// Next byte ready to read from serial
|
||||
head = (rxhead + 1) & USART_RXBUF_MASK;
|
||||
// Free space in RX buffer?
|
||||
if (head != rxtail) {
|
||||
// Copy from register
|
||||
rxbuf[head] = UDR;
|
||||
rxhead = head;
|
||||
} else {
|
||||
// XXX: Discard overflow
|
||||
}
|
||||
}
|
||||
|
||||
// INT: Data register empty
|
||||
ISR(USART_UDRE_vect)
|
||||
{
|
||||
short tail;
|
||||
|
||||
// Anything in TX buffer?
|
||||
if (txhead != txtail) {
|
||||
// Write next byte to data register
|
||||
tail = (txtail + 1) & USART_TXBUF_MASK;
|
||||
UDR = txbuf[tail];
|
||||
txtail = tail;
|
||||
} else {
|
||||
// Disable interrupt
|
||||
UCSRB &= ~BIT(UDRIE);
|
||||
}
|
||||
}
|
||||
8
src/bus/usart.h
Normal file
8
src/bus/usart.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef MAD_CORE_BUS_USART_H
|
||||
#define MAD_CORE_BUS_USART_H
|
||||
|
||||
int USART_Init(void);
|
||||
void USART_Putc(char ch);
|
||||
char USART_Getc(void);
|
||||
|
||||
#endif // MAD_CORE_BUS_USART_H
|
||||
Reference in New Issue
Block a user