-
Notifications
You must be signed in to change notification settings - Fork 1
/
uart.cpp
104 lines (97 loc) · 2.26 KB
/
uart.cpp
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
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
* Copyright (c) 2016, Łukasz Marcin Podkalicki <[email protected]>
* Software UART for ATtiny13
*/
#include <avr/interrupt.h>
#include "uart.h"
char
uart_getc(void)
{
#ifdef UART_RX_ENABLED
char c;
uint8_t sreg;
sreg = SREG;
cli();
PORTB &= ~(1 << UART_RX);
DDRB &= ~(1 << UART_RX);
__asm volatile(
" ldi r18, %[rxdelay2] \n\t" // 1.5 bit delay
" ldi %0, 0x80 \n\t" // bit shift counter
"WaitStart: \n\t"
" sbic %[uart_port]-2, %[uart_pin] \n\t" // wait for start edge
" rjmp WaitStart \n\t"
"RxBit: \n\t"
// 6 cycle loop + delay - total = 5 + 3*r22
// delay (3 cycle * r18) -1 and clear carry with subi
" subi r18, 1 \n\t"
" brne RxBit \n\t"
" ldi r18, %[rxdelay] \n\t"
" sbic %[uart_port]-2, %[uart_pin] \n\t" // check UART PIN
" sec \n\t"
" ror %0 \n\t"
" brcc RxBit \n\t"
"StopBit: \n\t"
" dec r18 \n\t"
" brne StopBit \n\t"
: "=r" (c)
: [uart_port] "I" (_SFR_IO_ADDR(PORTB)),
[uart_pin] "I" (UART_RX),
[rxdelay] "I" (RXDELAY),
[rxdelay2] "I" (RXDELAY2)
: "r0","r18","r19"
);
SREG = sreg;
return c;
#else
return (-1);
#endif /* !UART_RX_ENABLED */
}
void
uart_putc(char c)
{
#ifdef UART_TX_ENABLED
uint8_t sreg;
sreg = SREG;
cli();
PORTB |= 1 << UART_TX;
DDRB |= 1 << UART_TX;
__asm volatile(
" cbi %[uart_port], %[uart_pin] \n\t" // start bit
" in r0, %[uart_port] \n\t"
" ldi r30, 3 \n\t" // stop bit + idle state
" ldi r28, %[txdelay] \n\t"
"TxLoop: \n\t"
// 8 cycle loop + delay - total = 7 + 3*r22
" mov r29, r28 \n\t"
"TxDelay: \n\t"
// delay (3 cycle * delayCount) - 1
" dec r29 \n\t"
" brne TxDelay \n\t"
" bst %[ch], 0 \n\t"
" bld r0, %[uart_pin] \n\t"
" lsr r30 \n\t"
" ror %[ch] \n\t"
" out %[uart_port], r0 \n\t"
" brne TxLoop \n\t"
:
: [uart_port] "I" (_SFR_IO_ADDR(PORTB)),
[uart_pin] "I" (UART_TX),
[txdelay] "I" (TXDELAY),
[ch] "r" (c)
: "r0","r28","r29","r30"
);
SREG = sreg;
#endif /* !UART_TX_ENABLED */
}
void uart_putu(uint16_t x)
{
char buff[8] = {0};
char *p = buff+6;
do { *(p--) = (x % 10) + '0'; x /= 10; } while(x);
uart_puts((const char *)(p+1));
}
void
uart_puts(const char *s)
{
while (*s) uart_putc(*(s++));
}