FastLED 3.9.15
Loading...
Searching...
No Matches
serial.cpp.hpp
Go to the documentation of this file.
1// Arduino-compatible Serial API implementation
2
3#pragma once
4
5#include "fl/system/serial.h"
6#include "fl/stl/cstdio.h"
7#include "fl/stl/charconv.h"
8#include "fl/stl/cstring.h"
9#include "fl/stl/chrono.h"
10
11namespace fl {
12
13// ============================================================================
14// SerialPort Implementation
15// ============================================================================
16
17void SerialPort::begin(u32 baudRate) {
18 fl::serial_begin(baudRate);
19}
20
22 // Most platforms don't need explicit end() call
23 // Serial is always available for debugging
24}
25
27 return fl::available();
28}
29
31 return fl::read();
32}
33
35 return fl::peek();
36}
37
38size_t SerialPort::write(u8 byte) {
39 char str[2] = {static_cast<char>(byte), '\0'};
40 fl::print(str);
41 return 1;
42}
43
44size_t SerialPort::write(const u8* buffer, size_t size) {
45 return fl::write_bytes(buffer, size);
46}
47
48size_t SerialPort::print(const char* str) {
49 if (!str) {
50 return 0;
51 }
52
53 fl::print(str);
54 return fl::strlen(str);
55}
56
58 char buffer[12]; // Enough for "-2147483648" + null
59 fl::itoa(value, buffer, 10); // Base 10
60 return print(buffer);
61}
62
64 char buffer[21]; // Enough for 64-bit values
65 fl::itoa64(value, buffer, 10); // Base 10
66 return print(buffer);
67}
68
69// Template implementation for unsigned multi-byte integers
70// Handles both u32 and unsigned long, avoiding duplicate overloads on platforms where they're the same type
71template<typename T>
74 size_t>::type
76 char buffer[21]; // Enough for 64-bit values
77
78 // Use utoa64 for all types - it handles both 32-bit and 64-bit values
79 // This avoids needing C++17 constexpr if
80 fl::utoa64(static_cast<fl::u64>(value), buffer, 10);
81
82 return print(buffer);
83}
84
85size_t SerialPort::println(const char* str) {
86 if (!str) {
87 return println();
88 }
89
90 fl::println(str);
91 return fl::strlen(str) + 1; // +1 for newline
92}
93
95 fl::println("");
96 return 1; // Just the newline
97}
98
100 char buffer[12];
101 fl::itoa(value, buffer, 10);
102 return println(buffer);
103}
104
106 char buffer[21];
107 fl::itoa64(value, buffer, 10);
108 return println(buffer);
109}
110
111// Template implementation for unsigned multi-byte integers
112// Handles both u32 and unsigned long, avoiding duplicate overloads on platforms where they're the same type
113template<typename T>
116 size_t>::type
118 char buffer[21]; // Enough for 64-bit values
119
120 // Use utoa64 for all types - it handles both 32-bit and 64-bit values
121 // This avoids needing C++17 constexpr if
122 fl::utoa64(static_cast<fl::u64>(value), buffer, 10);
123
124 return println(buffer);
125}
126
127// Note: printf() is now implemented as an inline template in serial.h
128
129bool SerialPort::flush(u32 timeoutMs) {
130 return fl::flush(timeoutMs);
131}
132
133SerialPort::operator bool() const {
134 return fl::serial_ready();
135}
136
137void SerialPort::setTimeout(u32 timeoutMs) {
138 mTimeoutMs = timeoutMs;
139}
140
143 u32 startTime = fl::millis();
144
145 while (fl::millis() - startTime < mTimeoutMs) {
146 if (available() > 0) {
147 int c = read();
148 if (c != -1) {
149 result += static_cast<char>(c);
150 startTime = fl::millis(); // Reset timeout on successful read
151 }
152 }
153 }
154
155 return result;
156}
157
160 u32 startTime = fl::millis();
161
162 while (fl::millis() - startTime < mTimeoutMs) {
163 if (available() > 0) {
164 int c = read();
165 if (c == -1) {
166 continue; // No data
167 }
168 if (c == delimiter) {
169 break; // Found delimiter, stop reading
170 }
171 result += static_cast<char>(c);
172 startTime = fl::millis(); // Reset timeout on successful read
173 }
174 }
175
176 return result;
177}
178
179size_t SerialPort::readBytes(u8* buffer, size_t length) {
180 if (!buffer || length == 0) {
181 return 0;
182 }
183
184 size_t count = 0;
185 u32 startTime = fl::millis();
186
187 while (count < length && (fl::millis() - startTime < mTimeoutMs)) {
188 if (available() > 0) {
189 int c = read();
190 if (c != -1) {
191 buffer[count++] = static_cast<u8>(c);
192 startTime = fl::millis(); // Reset timeout on successful read
193 }
194 }
195 }
196
197 return count;
198}
199
200size_t SerialPort::readBytesUntil(char delimiter, u8* buffer, size_t length) {
201 if (!buffer || length == 0) {
202 return 0;
203 }
204
205 size_t count = 0;
206 u32 startTime = fl::millis();
207
208 while (count < length && (fl::millis() - startTime < mTimeoutMs)) {
209 if (available() > 0) {
210 int c = read();
211 if (c == -1) {
212 continue; // No data
213 }
214 if (c == delimiter) {
215 break; // Found delimiter, stop reading
216 }
217 buffer[count++] = static_cast<u8>(c);
218 startTime = fl::millis(); // Reset timeout on successful read
219 }
220 }
221
222 return count;
223}
224
226 bool negative = false;
227 long value = 0;
228 bool foundDigit = false;
229 u32 startTime = fl::millis();
230
231 // Skip non-numeric characters
232 while (fl::millis() - startTime < mTimeoutMs) {
233 if (available() > 0) {
234 int c = peek();
235 if (c == -1) {
236 continue;
237 }
238
239 // Check for sign
240 if (c == '-') {
241 negative = true;
242 read(); // Consume the sign
243 break;
244 } else if (c == '+') {
245 read(); // Consume the sign
246 break;
247 } else if (c >= '0' && c <= '9') {
248 break; // Found a digit
249 } else {
250 read(); // Skip non-numeric character
251 startTime = fl::millis(); // Reset timeout
252 }
253 }
254 }
255
256 // Parse digits
257 startTime = fl::millis();
258 while (fl::millis() - startTime < mTimeoutMs) {
259 if (available() > 0) {
260 int c = peek();
261 if (c == -1) {
262 continue;
263 }
264
265 if (c >= '0' && c <= '9') {
266 value = value * 10 + (c - '0');
267 read(); // Consume the digit
268 foundDigit = true;
269 startTime = fl::millis(); // Reset timeout
270 } else {
271 break; // Non-digit, stop parsing
272 }
273 }
274 }
275
276 return foundDigit ? (negative ? -value : value) : 0;
277}
278
280 bool negative = false;
281 long intPart = 0;
282 long fracPart = 0;
283 int fracDigits = 0;
284 bool foundDigit = false;
285 bool inFraction = false;
286 u32 startTime = fl::millis();
287
288 // Skip non-numeric characters
289 while (fl::millis() - startTime < mTimeoutMs) {
290 if (available() > 0) {
291 int c = peek();
292 if (c == -1) {
293 continue;
294 }
295
296 // Check for sign
297 if (c == '-') {
298 negative = true;
299 read(); // Consume the sign
300 break;
301 } else if (c == '+') {
302 read(); // Consume the sign
303 break;
304 } else if (c >= '0' && c <= '9') {
305 break; // Found a digit
306 } else if (c == '.') {
307 break; // Found decimal point
308 } else {
309 read(); // Skip non-numeric character
310 startTime = fl::millis(); // Reset timeout
311 }
312 }
313 }
314
315 // Parse digits (integer and fractional parts)
316 startTime = fl::millis();
317 while (fl::millis() - startTime < mTimeoutMs) {
318 if (available() > 0) {
319 int c = peek();
320 if (c == -1) {
321 continue;
322 }
323
324 if (c == '.' && !inFraction) {
325 inFraction = true;
326 read(); // Consume decimal point
327 foundDigit = true; // Decimal point counts as finding a number
328 startTime = fl::millis(); // Reset timeout
329 } else if (c >= '0' && c <= '9') {
330 if (inFraction) {
331 fracPart = fracPart * 10 + (c - '0');
332 fracDigits++;
333 } else {
334 intPart = intPart * 10 + (c - '0');
335 }
336 read(); // Consume the digit
337 foundDigit = true;
338 startTime = fl::millis(); // Reset timeout
339 } else {
340 break; // Non-digit, stop parsing
341 }
342 }
343 }
344
345 if (!foundDigit) {
346 return 0.0f;
347 }
348
349 // Calculate float value
350 float value = static_cast<float>(intPart);
351 if (fracDigits > 0) {
352 float divisor = 1.0f;
353 for (int i = 0; i < fracDigits; i++) {
354 divisor *= 10.0f;
355 }
356 value += static_cast<float>(fracPart) / divisor;
357 }
358
359 return negative ? -value : value;
360}
361
362// ============================================================================
363// Global Serial object
364// ============================================================================
365
366// Note: FL_MAYBE_UNUSED on extern declaration (in header) is enough
367// Don't use it on definition or linker won't export the symbol
369
370} // namespace fl
FastLED chrono implementation - duration types for time measurements.
int peek()
Peek at next byte without removing it from buffer.
bool flush(u32 timeoutMs=1000)
Wait for serial output to complete.
void begin(u32 baudRate=115200)
Initialize serial communication.
fl::string readString()
Read all available bytes into a string.
size_t print(const char *str)
Print string to serial output.
float parseFloat()
Parse floating-point number from serial input.
size_t println()
Print newline only.
fl::string readStringUntil(char delimiter)
Read characters until delimiter is found.
void setTimeout(u32 timeoutMs)
Set timeout for read operations.
size_t write(u8 byte)
Write single byte to serial output.
size_t readBytesUntil(char delimiter, u8 *buffer, size_t length)
Read bytes until delimiter is found.
long parseInt()
Parse integer from serial input.
int available()
Check how many bytes are available to read.
void end()
Close serial communication.
int read()
Read next byte from serial input.
size_t readBytes(u8 *buffer, size_t length)
Read fixed number of bytes into buffer.
Arduino-compatible Serial class for cross-platform serial I/O.
Definition serial.h:38
fl::UISlider length("Length", 1.0f, 0.0f, 1.0f, 0.01f)
uint8_t byte
Definition midi_Defs.h:36
int available()
unsigned char u8
Definition stdint.h:131
constexpr int type_rank< T >::value
int read()
SerialPort fl_serial
int peek()
int itoa(i32 value, char *sp, int radix)
Convert signed 32-bit integer to string buffer in given radix.
void print(const char *str)
size_t strlen(const char *s) FL_NOEXCEPT
int utoa64(u64 value, char *sp, int radix)
Convert unsigned 64-bit integer to string buffer in given radix.
fl::u32 millis()
Universal millisecond timer - returns milliseconds since system startup.
void serial_begin(u32 baudRate)
int itoa64(i64 value, char *sp, int radix)
Convert signed 64-bit integer to string buffer in given radix.
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
bool serial_ready()
size_t write_bytes(const u8 *buffer, size_t size)
fl::u64 u64
Definition s16x16x4.h:221
void println(const char *str) FL_NOEXCEPT
bool flush(u32 timeoutMs)
Base definition for an LED controller.
Definition crgb.hpp:179