aboutsummaryrefslogtreecommitdiff
path: root/src/usart.c
blob: 0e17aff7fef52c37f9d8e0e4686f8a593a46e107 (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include "../usart.h"

#ifdef MCUSUPPORT_USART

volatile int8_t _usart_busy;

inline void usart_init_uart(void) {
    usart_init_async(USART_BAUDRATE_115200, USART_PARITY_NONE,
                     USART_STOPBIT_SINGLE, USART_DATABITS_8);
}

void usart_init_async(enum usartBaudrate baudrate,
                      enum usartParity parity, enum usartStopBit stopbit,
                      enum usartDataBits databits) {
    _usart_busy = 0;
    switch (baudrate) {
    case USART_BAUDRATE_2400:
#define BAUD 2400
#include "usart_baundrate_helper.h"
        break;
    case USART_BAUDRATE_4800:
#define BAUD 4800
#include "usart_baundrate_helper.h"
        break;
    case USART_BAUDRATE_9600:
#define BAUD 9600
#include "usart_baundrate_helper.h"
        break;
    case USART_BAUDRATE_19200:
#define BAUD 19200
#include "usart_baundrate_helper.h"
        break;
    case USART_BAUDRATE_38400:
#define BAUD 38400
#include "usart_baundrate_helper.h"
        break;
    case USART_BAUDRATE_57600:
#define BAUD 57600
#include "usart_baundrate_helper.h"
        break;
    case USART_BAUDRATE_115200:
#define BAUD 115200
#include "usart_baundrate_helper.h"
        break;
    }
    switch (parity) {
    case USART_PARITY_NONE:
        UCSR0C &= ~(_BV(UPM00) | _BV(UPM01));
        break;
    case USART_PARITY_ODD:
        UCSR0C &= ~_BV(UPM00);
        UCSR0C |= _BV(UPM01);
        break;
    case USART_PARITY_EVEN:
        UCSR0C |= _BV(UPM00) | _BV(UPM01);
        break;
    }
    switch (stopbit) {
    case USART_STOPBIT_SINGLE:
        UCSR0C &= ~_BV(USBS0);
        break;
    case USART_STOPBIT_DOUBLE:
        UCSR0C |= _BV(USBS0);
        break;
    }
    switch (databits) {
    case USART_DATABITS_5:
        UCSR0C &= ~(_BV(UCSZ00) | _BV(UCSZ01));
        break;
    case USART_DATABITS_6:
        UCSR0C &= ~_BV(UCSZ01);
        UCSR0C |= _BV(UCSZ00);
        break;
    case USART_DATABITS_7:
        UCSR0C &= ~_BV(UCSZ00);
        UCSR0C |= _BV(UCSZ01);
        break;
    case USART_DATABITS_8:
        UCSR0C |= _BV(UCSZ00) | _BV(UCSZ01);
        break;
    }
    // Enable receiver, transmitter and RX complete,
    // Data register empty interrupts
    UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0) | _BV(UDRIE0);
#ifdef _IOE_USART_INBUFFER
    IOEBUFFER_INIT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE);
#endif
#ifdef _IOE_USART_OUTBUFFER
    IOEBUFFER_INIT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE);
#endif
}

inline void usart_send(uint8_t data) {
#ifdef _IOE_USART_OUTBUFFER
    if (!_usart_busy) {
        _usart_busy = 1;
        UDR0 = data;
    } else {
        IOEBUFFER_PUT(_ioe_usart_outbuffer,
                      CONFIG_IOE_USART_OUTBUFFER_SIZE, data,
                      CONFIG_IOE_USART_OUTBUFFER_MODE);
    }
#else
    _usart_busy = 1;
    UDR0 = data;
#endif /* _IOE_USART_OUTBUFFER */
}

#ifdef _IOE_USART_OUTBUFFER
void usart_send_str(char *str) {
    while (*str != '\0') {
        usart_send((uint8_t) * str);
        str++;
    }
}
#endif /* _IOE_USART_OUTBUFFER */

#ifdef _IOE_USART_INBUFFER
uint8_t usart_get(void) {
    uint8_t rtn = 0;
    IOEBUFFER_GET(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE,
                  rtn);
    return rtn;
}
#endif

inline uint8_t usart_queryerror(void) {
    return UCSR0A & (_BV(FE0) | _BV(DOR0) | _BV(UPE0));
}

inline int8_t usart_busy(void) {
    return _usart_busy;
}

#ifdef _IOE_USART_INBUFFER
uint8_t usart_inbuffered(void) {
    uint8_t rtn;
    IOEBUFFER_CNT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE,
                  rtn);
    return rtn;
}
#endif

#ifdef _IOE_USART_OUTBUFFER
uint8_t usart_outbuffered(void) {
    uint8_t rtn;
    IOEBUFFER_CNT(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE,
                  rtn);
    return rtn;
}
#endif

////// Interrupts ////////////////////////////////
void (*usart_receive) (uint8_t data) = 0;
void (*usart_sent) (void) = 0;

SIGNAL(USART_RX_vect) {
#ifdef _IOE_USART_INBUFFER
    uint8_t val = UDR0;
    IOEBUFFER_PUT(_ioe_usart_inbuffer, CONFIG_IOE_USART_INBUFFER_SIZE,
                  val, CONFIG_IOE_USART_INBUFFER_MODE);
#endif /* _IOE_USART_INBUFFER */
    if (usart_receive)
        usart_receive(UDR0);
}

SIGNAL(USART_UDRE_vect) {
#ifdef _IOE_USART_OUTBUFFER
    uint8_t val;
    IOEBUFFER_GET(_ioe_usart_outbuffer, CONFIG_IOE_USART_OUTBUFFER_SIZE,
                  val);
    if (val)
        UDR0 = val;
    else
        _usart_busy = 0;
#else
    _usart_busy = 0;
#endif /* _IOE_USART_OUTBUFFER */
    if (usart_sent)
        usart_sent();
}

#endif