// 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 . */ #include "RF433Serial.h" #include 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