RF433any/RF433Serial.cpp

105 lines
3.1 KiB
C++

// Serial.cpp
/*
Provides a way to read lines on serial
*/
/*
Copyright 2021 Sébastien Millet
`rf433any' is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
`rf433any' is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program. If not, see
<https://www.gnu.org/licenses>.
*/
#include "RF433Serial.h"
#include <Arduino.h>
RF433SerialLine::RF433SerialLine():head(0),got_a_line(false) { };
void RF433SerialLine::do_events() {
if (got_a_line)
return;
if (!Serial.available())
return;
int b;
do {
b = Serial.read();
if (b == -1)
break;
buf[head++] = (char)b;
} while (head < RF433SERIAL_LINE_BUF_LEN - 1
&& b != '\n' && Serial.available());
if (head < RF433SERIAL_LINE_BUF_LEN - 1 && b != '\n')
return;
buf[head] = '\0';
// Remove trailing cr and/or nl
// FIXME?
// WON'T WORK WITH MAC-OS NEWLINES!
// (SEE ABOVE: NO STOP IF ONLY CR ENCOUNTERED)
if (head >= 1 && buf[head - 1] == '\n')
buf[--head] = '\0';
if (head >= 1 && buf[head - 1] == '\r')
buf[--head] = '\0';
got_a_line = true;
}
bool RF433SerialLine::is_line_available() {
do_events();
return got_a_line;
}
void RF433SerialLine::reset() {
head = 0;
got_a_line = false;
}
// Get USB input as a simple line, copied in caller buffer.
// A 'line' is a set of non-null characters followed by 'new line', 'new line'
// being either as per Unix or Windows convention, see below.
// Returns true if a copy was done (there was a line available), false if not
// (in which case, s is not updated).
// The terminating newline character (or 2-character CR-LF sequence) is NOT part
// of the string given to the caller.
// If the line length is above the buffer size (RF433SERIAL_LINE_BUF_LEN), then
// it'll be cut into smaller pieces.
// Because of the way the received buffer is parsed, and when using CR-LF as
// end-of-line marker (default even under Linux), it can result in a empty
// string seen after a first string with a length close to the limit.
//
// About new lines:
// - Works fine with Unix new lines (\n), tested
// - Supposed to work fine with Windows new lines (\r\n), NOT TESTED
// - WON'T WORK WITH MAC-OS NEW LINES (\r)
bool RF433SerialLine::get_line(char *s, size_t len) {
do_events();
if (!got_a_line)
return false;
snprintf(s, len, buf);
reset();
return true;
}
// Same as get_line, but with blocking I/O =
// Wait without time limit, until a line comes in.
void RF433SerialLine::get_line_blocking(char *s, size_t len) {
while (!get_line(s, len))
;
}
// vim: ts=4:sw=4:tw=80:et