forked from Duet3D/RepRapFirmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLine.cpp
More file actions
174 lines (159 loc) · 4.04 KB
/
Line.cpp
File metadata and controls
174 lines (159 loc) · 4.04 KB
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
#include "Arduino.h"
#include "Line.h"
//***************************************************************************************************
// Serial/USB class
Line::Line(Stream& p_iface) : iface(p_iface)
{
}
uint8_t Line::Status() const
{
return inputNumChars == 0 ? (uint8_t)IOStatus::nothing : (uint8_t)IOStatus::byteAvailable;
}
// This is only ever called on initialisation, so we know the buffer won't overflow
void Line::InjectString(char* string)
{
int i = 0;
while(string[i])
{
inBuffer[(inputGetIndex + inputNumChars) % lineInBufsize] = string[i];
inputNumChars++;
i++;
}
}
int Line::Read(char& b)
{
if (inputNumChars == 0)
return 0;
b = inBuffer[inputGetIndex];
inputGetIndex = (inputGetIndex + 1) % lineInBufsize;
--inputNumChars;
return 1;
}
void Line::Init()
{
inputGetIndex = 0;
inputNumChars = 0;
outputGetIndex = 0;
outputNumChars = 0;
ignoringOutputLine = false;
inWrite = 0;
outputColumn = 0;
timeLastCharWritten = 0;
}
void Line::Spin()
{
// Read the serial data in blocks to avoid excessive flow control
if (inputNumChars <= lineInBufsize / 2)
{
int16_t target = iface.available() + (int16_t) inputNumChars;
if (target > lineInBufsize)
{
target = lineInBufsize;
}
while ((int16_t) inputNumChars < target)
{
int incomingByte = iface.read();
if (incomingByte < 0)
break;
inBuffer[(inputGetIndex + inputNumChars) % lineInBufsize] = (char) incomingByte;
++inputNumChars;
}
}
TryFlushOutput();
}
// Write a character to USB.
// If 'important' is true then we don't return until we have either written it to the USB port,
// or put it in the buffer, or we have timed out waiting for the buffer to empty. The purpose of the timeout is to
// avoid getting a software watchdog reset if we are writing important data (e.g. debug) and there is no consumer for the data.
// Otherwise, if the buffer is full then we append ".\n" to the end of it, return immediately and ignore the rest
// of the data we are asked to print until we get a new line.
void Line::Write(char b, bool important)
{
if (b == '\n')
{
outputColumn = 0;
}
else
{
++outputColumn;
}
if (ignoringOutputLine)
{
// We have already failed to write some characters of this message line, so don't write any of it.
// But try to start sending again after this line finishes.
if (b == '\n')
{
ignoringOutputLine = false;
}
}
else
{
for(;;)
{
TryFlushOutput();
if (outputNumChars == 0 && iface.canWrite() != 0)
{
// We can write the character directly into the USB output buffer
++inWrite;
iface.write(b);
--inWrite;
timeLastCharWritten = millis();
break;
}
else if ( outputNumChars + 2 < lineOutBufSize // save 2 spaces in the output buffer
|| (b == '\n' && outputNumChars < lineOutBufSize) //...unless writing newline
)
{
outBuffer[(outputGetIndex + outputNumChars) % lineOutBufSize] = b;
++outputNumChars;
break;
}
else if (!important || millis() - timeLastCharWritten >= 100)
{
// Output is being consumed too slowly, so throw away some data
if (outputNumChars + 2 == lineOutBufSize)
{
// We still have our 2 free characters, so append ".\n" to the line to indicate it was incomplete
outBuffer[(outputGetIndex + outputNumChars) % lineOutBufSize] = '.';
++outputNumChars;
outBuffer[(outputGetIndex + outputNumChars) % lineOutBufSize] = '\n';
++outputNumChars;
}
else
{
// As we don't have 2 spare characters in the buffer, we can't have written any of the current line.
// So ignore the whole line.
}
ignoringOutputLine = true;
break;
}
}
}
}
void Line::Write(const char* b, bool important)
{
while (*b)
{
Write(*b++, important);
}
}
void Line::TryFlushOutput()
{
while (outputNumChars != 0 && iface.canWrite() != 0)
{
++inWrite;
iface.write(outBuffer[outputGetIndex]);
--inWrite;
timeLastCharWritten = millis();
outputGetIndex = (outputGetIndex + 1) % lineOutBufSize;
--outputNumChars;
}
}
void Line::Flush()
{
while (outputNumChars != 0)
{
TryFlushOutput();
}
}
// End