-
Notifications
You must be signed in to change notification settings - Fork 5
/
uart.c
157 lines (132 loc) · 3.35 KB
/
uart.c
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
#include "uart.h"
#include <stddef.h>
#include <stdint.h>
#include "stm8.h"
#include "settings.h"
#include "strings.h"
#include "ringbuffer.h"
enum RxState {
RxState_Start,
RxState_H, // waiting for high byte half
RxState_L, // waiting low byte half
RxState_Stop // '\n' received, but buffer not read yet
};
static enum RxState rxState = RxState_Start;
static uint8_t rxBuf[UART_RXBUF_SIZE];
static uint8_t rxBufPos;
static bool hasChecksum;
void UART_write(const char *str) {
for(; *str; ++str)
UART_send((uint8_t)*str);
}
void UART_writeHexU8(uint8_t v) {
UART_send(HEX_DIGITS[v >> 4]);
UART_send(HEX_DIGITS[v & 0x0F]);
}
void UART_writeHexU16(uint16_t v) {
UART_writeHexU8(v >> 8);
UART_writeHexU8(v & 0xFF);
}
void UART_writeHexU32(uint32_t v) {
UART_writeHexU8(v >> 24);
UART_writeHexU8(v >> 16);
UART_writeHexU8(v >> 8);
UART_writeHexU8(v & 0xFF);
}
void UART_writeDecU16(uint16_t v) {
UART_writeDecU64(v, 5);
}
void UART_writeDecU32(uint32_t v) {
UART_writeDecU64(v, 10);
}
void UART_writeDecU64(uint64_t v, uint8_t n) {
char buf[22];
uint8_t i;
for(i = 0; i < n; ++i) buf[i] = ' ';
buf[n] = '\0';
i = n;
do {
uint8_t d = v % 10;
v /= 10;
buf[--i] = '0' + d;
}
while(v != 0);
UART_write(buf);
}
static inline void resetRx(void) {
rxBufPos = 0;
rxState = RxState_Start;
}
const uint8_t* UART_getRx(uint8_t* size) {
if(rxState == RxState_Stop) {
*size = rxBufPos;
return rxBuf;
}
else {
return NULL;
}
}
bool UART_hasChecksum(void) {
return hasChecksum;
}
void UART_rxDone(void) {
resetRx();
}
// 2-5.3 us
void UART_process(void) {
uint8_t v;
uint8_t b;
if(!RINGBUFFER_takeIfNotEmpty(&b)) return;
if(rxState != RxState_Stop) {
if(b == 'S' || b == 's') { // start
resetRx();
rxState = RxState_H;
hasChecksum = (b == 'S');
return;
}
}
switch(rxState) {
case RxState_H:
case RxState_L:
if(b >= '0' && b <= '9') {
v = b - '0';
}
else if(b >= 'A' && b <= 'F') {
v = b - 'A' + 10;
}
else if(b == '\n') { // ignore
break;
}
else if(b == '\r') { // stop
if(rxState == RxState_L) // unexpected, reset
resetRx();
else
rxState = RxState_Stop;
break;
}
else { // unexpected symbol, reset
resetRx();
break;
}
if(rxState == RxState_H) {
rxBuf[rxBufPos] = (v << 4);
rxState = RxState_L;
}
else {
rxBuf[rxBufPos] |= v;
rxState = RxState_H;
++rxBufPos;
if(rxBufPos >= UART_RXBUF_SIZE) resetRx();
}
break;
case RxState_Start:
case RxState_Stop:
nop(); // who are the EVELYN and the DOG?
break; // ignore all
}
}
// ~ 5.5us
void UART_UART2_rx(void) __interrupt(IRQN_UART2_RX) {
(void)UART2->SR; // reset and ignore Overrun, if any
RINGBUFFER_addIfNotFull(UART2->DR); // reset RXNE
}