-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSerialActivity.h
111 lines (98 loc) · 3.81 KB
/
SerialActivity.h
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
#pragma once
class String;
#include <HardwareSerial.h>
template <typename DerivedType, typename _SerialType>
class SerialActivity : public Activity, public WriteStream<SerialActivity<DerivedType,_SerialType>> {
public:
using SerialType = _SerialType;
static constexpr int MaxIncomingSize = 256;
static constexpr int MaxOutgoingSize = 256;
SerialType Port;
SerialActivity()
: IncomingBufferSize(0)
, OutgoingBufferSize(0)
{}
void OnReceived(const AW::StringBuf& buf) {
static_cast<DerivedType*>(this)->OnSerialReceived(buf);
}
void Setup(int baud) {
}
void OnLoop(const ActivityContext&) {
int incomingSize = MaxIncomingSize - IncomingBufferSize;
if (incomingSize > 0) {
int availableForRead = Port.AvailableForRead();
int size = incomingSize > availableForRead ? availableForRead : incomingSize;
if (size > 0) {
int strStart = 0;
int bufferPos = IncomingBufferSize;
size = Port.readBytes(&IncomingBuffer[IncomingBufferSize], size);
IncomingBufferSize += size;
while (bufferPos < IncomingBufferSize) {
if (IncomingBuffer[bufferPos] == '\n') {
int strSize = bufferPos;
while (strSize > 0 && IncomingBuffer[strSize - 1] == '\r') {
--strSize;
}
OnReceived(StringBuf(&IncomingBuffer[strStart], strSize));
strStart = bufferPos + 1;
}
++bufferPos;
}
IncomingBufferSize = bufferPos - strStart;
if (IncomingBufferSize > 0) {
memmove(IncomingBuffer, &IncomingBuffer[strStart], IncomingBufferSize);
}
}
}
if (OutgoingBufferSize > 0) {
int availableForWrite = Port.AvailableForWrite();
int size = OutgoingBufferSize > availableForWrite ? availableForWrite : OutgoingBufferSize;
if (size > 0) {
size = Port.write(OutgoingBuffer, size);
OutgoingBufferSize -= size;
if (OutgoingBufferSize > 0) {
memmove(OutgoingBuffer, &OutgoingBuffer[size], OutgoingBufferSize);
}
}
}
}
void send(const AW::StringBuf& str) {
AW::StringBuf s(str);
if (OutgoingBufferSize == 0) {
int availableForWrite = Port.AvailableForWrite();
int size = s.size() > availableForWrite ? availableForWrite : s.size();
size = Port.write(s.data(), size);
if (size == s.size())
return;
s = str.substr(size);
}
int sz = s.size();
if (sz > MaxOutgoingSize - OutgoingBufferSize)
sz = MaxOutgoingSize - OutgoingBufferSize;
memmove(&OutgoingBuffer[OutgoingBufferSize], s.data(), sz);
OutgoingBufferSize += sz;
}
bool IsAvailableForSend(int size) {
return MaxOutgoingSize - OutgoingBufferSize >= size;
}
protected:
char IncomingBuffer[MaxIncomingSize];
char OutgoingBuffer[MaxOutgoingSize];
int IncomingBufferSize;
int OutgoingBufferSize;
};
template <typename DerivedType, typename _SerialType>
class SerialConsole : public SerialActivity<SerialConsole<DerivedType, _SerialType>, _SerialType> {
public:
SerialConsole<DerivedType, _SerialType>& Console;
constexpr static bool OK = true;
SerialConsole()
: Console(*this)
{}
void Setup(int baud) {
SerialActivity<SerialConsole<DerivedType, _SerialType>, _SerialType>::Setup(baud);
}
void OnSerialReceived(const AW::StringBuf& buf) {
static_cast<DerivedType*>(this)->OnSerialReceived(buf);
}
};