summaryrefslogtreecommitdiff
path: root/uart.c
blob: 1f2656aca9c1e3917f2fc3845ea555c1cdc757fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#define TXBSIZE 128
static volatile char txbuf[TXBSIZE];
static volatile uint8_t txput = 0, txsend = 0;

ISR(USART_RX_vect)
{
	uint8_t data = UDR0;
}

ISR(USART_UDRE_vect)
{
	if (txsend != txput) {
		UDR0 = txbuf[txsend];
		txsend++;
		txsend &= TXBSIZE - 1;
		UCSR0B = (1 << RXCIE0) | (1 << UDRIE0) | (1 << RXEN0) | (1 << TXEN0);
	} else {
		UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0);
	}
}

static void uart_wait(void)
{
	while (txsend != txput)
		asm volatile ("" : : : "memory");
}

static void _uart_putch(const char ch)
{
	txbuf[txput] = ch;
	txput++;
	txput &= TXBSIZE - 1;
}

static void uart_putpgm(PGM_P str)
{
	char c;
	uint8_t sreg = SREG;
	cli();

	do {
		c = pgm_read_byte(str);
		if (!c)
			break;
		_uart_putch(c);
		str++;
	} while (1);
	if (UCSR0A & (1 << UDRE0))
		__vector_19();
	
	SREG = sreg;
}
#define uart_puts(str) do { \
	static const char _mystr[] PROGMEM = str; \
	uart_putpgm(_mystr); } while (0)

#define hexdigit(x) ((x) + '0' + ((x) > 9 ? ('a' - '0' - 10) : 0))
static void uart_puthex(uint8_t val)
{
	uint8_t tmp, sreg = SREG;
	cli();

	tmp = val >> 4;
	tmp += '0';
	if (tmp > '9')
		tmp += 'a' - '0' - 10;
	_uart_putch(tmp);
	tmp = val & 0xf;
	tmp += '0';
	if (tmp > '9')
		tmp += 'a' - '0' - 10;
	_uart_putch(tmp);
	if (UCSR0A & (1 << UDRE0))
		__vector_19();

	SREG = sreg;
}

static void uart_puthex16(uint16_t val)
{
	uart_puthex(val >> 8);
	uart_puthex(val & 0xff);
}

static void uart_init(void)
{
	UBRR0 = 12;	/* 38461 ~ 38400 */
	UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
	UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0);
}