Implement USART with bot RX and TX interrupts
This commit is contained in:
2
Makefile
2
Makefile
@@ -30,7 +30,7 @@ AVD := avrdude
|
|||||||
MKDIR := mkdir -p
|
MKDIR := mkdir -p
|
||||||
RMR := rm -rf
|
RMR := rm -rf
|
||||||
|
|
||||||
CPPFLAGS := -DF_CPU=$(FREQ)
|
CPPFLAGS := -DF_CPU=$(FREQ) -I$(SRCDIR)
|
||||||
CFLAGS := -mmcu=$(MCU) -Os -std=c99 -Wall -Wextra -Werror
|
CFLAGS := -mmcu=$(MCU) -Os -std=c99 -Wall -Wextra -Werror
|
||||||
OCFLAGS := -j .text -j .data -O ihex
|
OCFLAGS := -j .text -j .data -O ihex
|
||||||
LDFLAGS := -mmcu=$(MCU)
|
LDFLAGS := -mmcu=$(MCU)
|
||||||
|
|||||||
BIN
docs/PCA9546.pdf
Executable file
BIN
docs/PCA9546.pdf
Executable file
Binary file not shown.
Submodule opt/tools updated: 53be5b36f3...19702a0bb5
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
|
||||||
29
src/common.c
29
src/common.c
@@ -1,29 +0,0 @@
|
|||||||
#include "common.h"
|
|
||||||
#include "serial.h"
|
|
||||||
|
|
||||||
#define PREFIX_ERROR(fmt) "Error:" fmt
|
|
||||||
|
|
||||||
static bool state;
|
|
||||||
|
|
||||||
void Info(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
USART_Print(state, "", fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Error(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
USART_Print(state, "Error: ", fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetStateFlag(bool is_running)
|
|
||||||
{
|
|
||||||
state = is_running;
|
|
||||||
}
|
|
||||||
21
src/common.h
21
src/common.h
@@ -1,23 +1,12 @@
|
|||||||
#ifndef MAD_COMMON_H
|
#ifndef MAD_CORE_COMMON_H
|
||||||
#define MAD_COMMON_H
|
#define MAD_CORE_COMMON_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define BIT(n) (0x1U << (n))
|
#define BIT(n) (0x1U << (n))
|
||||||
#define UNUSED(s) (void)(s)
|
#define UNUSED(s) (void)(s)
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <util/delay.h>
|
|
||||||
#define Sleep(ms) _delay_ms(ms)
|
|
||||||
|
|
||||||
void Info(const char *fmt, ...);
|
void Info(const char *fmt, ...);
|
||||||
void Error(const char *fmt, ...);
|
void Error(const char *fmt, ...);
|
||||||
void SetStateFlag(bool is_running);
|
|
||||||
|
|
||||||
void Enable(void);
|
#endif // MAD_CORE_COMMON_H
|
||||||
void Disable(void);
|
|
||||||
void SetTemp(long val);
|
|
||||||
void SetDewp(long val);
|
|
||||||
|
|
||||||
#endif // MAD_COMMON_H
|
|
||||||
|
|||||||
24
src/common/common.c
Normal file
24
src/common/common.c
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "bus/usart.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static void Puts(const char *str)
|
||||||
|
{
|
||||||
|
while (*str) {
|
||||||
|
USART_Putc(*str++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Info(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char msg[256];
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
Puts("[CORE] ");
|
||||||
|
Puts(msg);
|
||||||
|
Puts("\r\n");
|
||||||
|
}
|
||||||
86
src/main.c
86
src/main.c
@@ -1,78 +1,28 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "serial.h"
|
#include "bus/usart.h"
|
||||||
#include "parser.h"
|
#include "bus/twi.h"
|
||||||
|
|
||||||
bool running;
|
#include <avr/interrupt.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#define Sleep(ms) _delay_ms(ms)
|
||||||
|
|
||||||
int main(void)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char ch;
|
|
||||||
unsigned long i = 1;
|
|
||||||
|
|
||||||
USART_Init();
|
USART_Init();
|
||||||
Enable();
|
TWI_Init();
|
||||||
|
|
||||||
for (;;) {
|
sei();
|
||||||
// Process rx ring buffer
|
|
||||||
while ((ch = USART_GetChar())) {
|
|
||||||
CMD_Parse(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
Sleep(3000);
|
Info("Initializing...");
|
||||||
if (running) {
|
Sleep(500);
|
||||||
// TODO: Main program
|
|
||||||
if (i >= 99999) i = 1;
|
// ADS1115 (ADC)
|
||||||
Info("Fetching sensors #%05lu...", i++);
|
// PCA9546 (Multiplexer TWI)
|
||||||
}
|
// ATH20 (3x)
|
||||||
}
|
// BMP280 (3x)
|
||||||
|
|
||||||
|
UNUSED(argc);
|
||||||
|
UNUSED(argv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Enable(void)
|
|
||||||
{
|
|
||||||
Info("Parsed 'CMD_RUN' token.");
|
|
||||||
if (running == true) {
|
|
||||||
Error("Already running.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
running = true;
|
|
||||||
SetStateFlag(running);
|
|
||||||
Info("Program started.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disable(void)
|
|
||||||
{
|
|
||||||
Info("Parsed 'CMD_STOP' token.");
|
|
||||||
if (running == false) {
|
|
||||||
Error("Already stopped.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
running = false;
|
|
||||||
SetStateFlag(running);
|
|
||||||
Info("Program stopped.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTemp(long val)
|
|
||||||
{
|
|
||||||
Info("Parsed 'CMD_SET_TEMP', VAL='%ld'.", val);
|
|
||||||
if (val < 10) {
|
|
||||||
Error("Given temperature is too low.");
|
|
||||||
return;
|
|
||||||
} else if (val > 40) {
|
|
||||||
Error("Given temperature is too high.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetDewp(long val)
|
|
||||||
{
|
|
||||||
Info("Parsed 'CMD_SET_DEWP', VAL='%ld'.", val);
|
|
||||||
if (val < 10) {
|
|
||||||
Error("Given dew point is too low.");
|
|
||||||
return;
|
|
||||||
} else if (val > 80) {
|
|
||||||
Error("Given dew point is too high.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
217
src/parser.c
217
src/parser.c
@@ -1,217 +0,0 @@
|
|||||||
#include "common.h"
|
|
||||||
#include "serial.h"
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* # Supported Commands
|
|
||||||
*
|
|
||||||
* - RUN
|
|
||||||
* - STOP
|
|
||||||
* - TEMP <num>
|
|
||||||
* - DEWP <num>
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int state;
|
|
||||||
static char numbuf[8];
|
|
||||||
static size_t numlen;
|
|
||||||
|
|
||||||
#define PARSE_IDLE 0
|
|
||||||
#define PARSE_CMD_RUN 1
|
|
||||||
#define PARSE_CMD_STOP 2
|
|
||||||
#define PARSE_CMD_SET_TEMP 3
|
|
||||||
#define PARSE_CMD_SET_DEWP 4
|
|
||||||
|
|
||||||
void CMD_Parse(char ch)
|
|
||||||
{
|
|
||||||
long num;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
switch (state) {
|
|
||||||
case PARSE_IDLE:
|
|
||||||
if (ch == 'R')
|
|
||||||
state = PARSE_CMD_RUN;
|
|
||||||
else if (ch == 'S')
|
|
||||||
state = PARSE_CMD_STOP;
|
|
||||||
else if (ch == 'T')
|
|
||||||
state = PARSE_CMD_SET_TEMP;
|
|
||||||
else if (ch == 'D')
|
|
||||||
state = PARSE_CMD_SET_DEWP;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PARSE_CMD_RUN:
|
|
||||||
break;
|
|
||||||
case PARSE_CMD_STOP:
|
|
||||||
break;
|
|
||||||
case PARSE_CMD_SET_TEMP:
|
|
||||||
break;
|
|
||||||
case PARSE_CMD_SET_DEWP:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Placeholder
|
|
||||||
switch (state) {
|
|
||||||
case 0:
|
|
||||||
if (ch == 'T') // TEMP
|
|
||||||
state = 1;
|
|
||||||
if (ch == 'D') // DEWP
|
|
||||||
state = 6;
|
|
||||||
if (ch == 'R') // RUN
|
|
||||||
state = 11;
|
|
||||||
if (ch == 'S') // STOP
|
|
||||||
state = 14;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Parse 'TEMP'
|
|
||||||
case 1:
|
|
||||||
if (ch == 'E')
|
|
||||||
state = 2;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (ch == 'M')
|
|
||||||
state = 3;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if (ch == 'P')
|
|
||||||
state = 4;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if (ch == ' ') {
|
|
||||||
numlen = 0;
|
|
||||||
state = 5;
|
|
||||||
} else {
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
// Error: Number too long
|
|
||||||
if (numlen >= sizeof(numbuf) - 1) {
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse numeric string
|
|
||||||
else if ((ch >= '0' && ch <= '9') || (!numlen && ch == '-')) {
|
|
||||||
numbuf[numlen++] = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse terminator and strip decimal
|
|
||||||
else if (ch == '\n' || ch == '.' || ch == ',') {
|
|
||||||
numbuf[numlen] = '\0';
|
|
||||||
num = strtol(numbuf, NULL, 10);
|
|
||||||
SetTemp(num);
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unexpected character
|
|
||||||
else {
|
|
||||||
Error("Unexpected character '%c'.", ch);
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Parse 'DEWP'
|
|
||||||
case 6:
|
|
||||||
if (ch == 'E')
|
|
||||||
state = 7;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
if (ch == 'W')
|
|
||||||
state = 8;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
if (ch == 'P')
|
|
||||||
state = 9;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
if (ch == ' ') {
|
|
||||||
numlen = 0;
|
|
||||||
state = 10;
|
|
||||||
} else {
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
// Error: Number too long
|
|
||||||
if (numlen >= sizeof(numbuf) - 1) {
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse numeric string
|
|
||||||
else if ((ch >= '0' && ch <= '9') || (!numlen && ch == '-')) {
|
|
||||||
numbuf[numlen++] = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse terminator and strip decimal
|
|
||||||
else if (ch == '\n' || ch == '.' || ch == ',') {
|
|
||||||
numbuf[numlen] = '\0';
|
|
||||||
num = strtol(numbuf, NULL, 10);
|
|
||||||
SetDewp(num);
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unexpected character
|
|
||||||
else {
|
|
||||||
Error("Unexpected character '%c'.", ch);
|
|
||||||
state = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Parse 'RUN'
|
|
||||||
case 11:
|
|
||||||
if (ch == 'U')
|
|
||||||
state = 12;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
if (ch == 'N')
|
|
||||||
state = 13;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
if (ch == '\n') {
|
|
||||||
Enable();
|
|
||||||
}
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Parse 'STOP'
|
|
||||||
case 14:
|
|
||||||
if (ch == 'T')
|
|
||||||
state = 15;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
if (ch == 'O')
|
|
||||||
state = 16;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
if (ch == 'P')
|
|
||||||
state = 17;
|
|
||||||
else
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
case 17:
|
|
||||||
if (ch == '\n') {
|
|
||||||
Disable();
|
|
||||||
}
|
|
||||||
state = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#ifndef MAD_PARSER_H
|
|
||||||
#define MAD_PARSER_H
|
|
||||||
|
|
||||||
void CMD_Parse(char ch);
|
|
||||||
|
|
||||||
#endif // MAD_PARSER_H
|
|
||||||
89
src/serial.c
89
src/serial.c
@@ -1,89 +0,0 @@
|
|||||||
#include "common.h"
|
|
||||||
#include "serial.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#define USART_BUFSIZE 512
|
|
||||||
#define USART_BAUDRATE 9600
|
|
||||||
#define USART_RXBUF_MASK (USART_BUFSIZE - 1)
|
|
||||||
#define USART_BAUD_PRESCALE ((((F_CPU / 16) + \
|
|
||||||
(USART_BAUDRATE / 2)) / (USART_BAUDRATE)) - 1)
|
|
||||||
|
|
||||||
// TODO: TX ring buffer
|
|
||||||
static unsigned char rxbuf[USART_BUFSIZE];
|
|
||||||
static unsigned char rxhead, rxtail;
|
|
||||||
|
|
||||||
void USART_Init(void)
|
|
||||||
{
|
|
||||||
rxhead = 0;
|
|
||||||
rxtail = 0;
|
|
||||||
|
|
||||||
// Handle RXC interrupt
|
|
||||||
UCSRB |= (1 << RXCIE);
|
|
||||||
sei();
|
|
||||||
|
|
||||||
UCSRB |= BIT(RXEN) | BIT(TXEN); // Enable rx and tx circuitry
|
|
||||||
UCSRC |= BIT(URSEL) | BIT(UCSZ0) | BIT(UCSZ1); // 8-bit chars
|
|
||||||
UBRRH = (USART_BAUD_PRESCALE >> 8); // Baud Rate upper byte
|
|
||||||
UBRRL = USART_BAUD_PRESCALE; // Baud rate lower byte
|
|
||||||
}
|
|
||||||
|
|
||||||
bool USART_IsDataAvailable(void)
|
|
||||||
{
|
|
||||||
return rxhead != rxtail;
|
|
||||||
}
|
|
||||||
|
|
||||||
char USART_GetChar(void)
|
|
||||||
{
|
|
||||||
unsigned char newtail;
|
|
||||||
|
|
||||||
if (!USART_IsDataAvailable()) {
|
|
||||||
return '\0'; // Non-blocking
|
|
||||||
}
|
|
||||||
|
|
||||||
newtail = (rxtail + 1) & USART_RXBUF_MASK;
|
|
||||||
rxtail = newtail;
|
|
||||||
|
|
||||||
return rxbuf[newtail];
|
|
||||||
}
|
|
||||||
|
|
||||||
void USART_PutChar(const char ch)
|
|
||||||
{
|
|
||||||
// Wait until UDR can receive data
|
|
||||||
while ((UCSRA & BIT(UDRE)) == 0);
|
|
||||||
UDR = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void USART_Print(bool state, const char *pre, const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
char buf[256], *ptr;
|
|
||||||
|
|
||||||
UNUSED(state);
|
|
||||||
len = sprintf(buf, "[CORE] %s", pre); //, state ? 'E' : 'D', pre);
|
|
||||||
vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
|
|
||||||
|
|
||||||
ptr = buf;
|
|
||||||
while (*ptr != '\0') {
|
|
||||||
USART_PutChar(*ptr++);
|
|
||||||
}
|
|
||||||
|
|
||||||
USART_PutChar('\r');
|
|
||||||
USART_PutChar('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interrupt Handler
|
|
||||||
ISR(USART_RXC_vect)
|
|
||||||
{
|
|
||||||
unsigned char newhead;
|
|
||||||
|
|
||||||
newhead = (rxhead + 1) & USART_RXBUF_MASK;
|
|
||||||
if (newhead == rxtail) {
|
|
||||||
// TODO: Handle overflow
|
|
||||||
} else {
|
|
||||||
rxhead = newhead;
|
|
||||||
rxbuf[newhead] = UDR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
13
src/serial.h
13
src/serial.h
@@ -1,13 +0,0 @@
|
|||||||
#ifndef MAD_SERIAL_H
|
|
||||||
#define MAD_SERIAL_H
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
void USART_Init(void);
|
|
||||||
char USART_GetChar(void);
|
|
||||||
void USART_PutChar(const char ch);
|
|
||||||
bool USART_IsDataAvailable(void);
|
|
||||||
void USART_Print(bool state, const char *pre, const char *fmt, va_list ap);
|
|
||||||
|
|
||||||
#endif // MAD_SERIAL_H
|
|
||||||
Reference in New Issue
Block a user