Skip to content

Commit

Permalink
Moved buffer to virtual serial device.
Browse files Browse the repository at this point in the history
  • Loading branch information
jfjlaros committed Feb 19, 2023
1 parent a691b9d commit 8b91f47
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 183 deletions.
148 changes: 41 additions & 107 deletions src/serialMux.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ enum Command : uint8_t {protocol, version, getPorts, enable, disable, reset};

/*! Serial multiplexer.
*
* \tparam maxPorts Maximum number of virtual serial ports.
* \tparam bits Buffer size control (2^`bits`).
*/
template <uint8_t bits=6>
template <uint8_t maxPorts, uint8_t bits>
class SerialMux_ {
public:
/*! Create a serial multiplexer.
Expand All @@ -22,122 +23,78 @@ public:
*/
SerialMux_(Stream& serial);

SerialMux_(SerialMux_ const&) = delete;

~SerialMux_();


SerialMux_& operator =(SerialMux_ const&) = delete;


/*! Add a virtual serial device.
*
* \return New virtual serial port.
* \return Virtual serial port number.
*/
uint8_t add();


/*! Get the number of bytes available for reading.
*
* \param[in] port Virtual serial port.
*
* \return Number of bytes.
*/
size_t available(uint8_t const port);

/*! Read one byte of data.
*
* \param[in] port Virtual serial port.
*
* \return The first byte of incoming data or `-1` if no data is available.
*/
int read(uint8_t const port);
uint8_t add(Buffer<bits>* buffer);

/*! Write one byte of data.
*
* \param[in] port Virtual serial port.
* \param[in] port Virtual serial port number.
* \param[in] data Data.
*
* \return Number of bytes written.
*/
void write(uint8_t const port, uint8_t const data);

/*! Return the next byte of incoming data without removing it from the
* buffer.
*
* \param[in] port Virtual serial port.
*
* \return The first byte of incoming data or `-1` if no data is available.
*/
int peek(uint8_t const port);
/*! Send incoming data to virtual serial ports. */
void update();

private:
void control_(uint8_t const);
void update_();

uint8_t read_() const;
void write_(uint8_t const, uint8_t const* const, uint8_t const);

Buffer<bits>* buffer_ {nullptr};
Buffer<bits>* buffer_[maxPorts] {};
bool enabled_ {false};
uint8_t portRx_ {controlPort_};
uint8_t portTx_ {controlPort_};
uint8_t ports_ {0};
Stream* serial_ {nullptr};
};

using SerialMux = SerialMux_<>; //!< Serial multiplexer.
using SerialMux = SerialMux_<4, 6>; //!< Serial multiplexer.


template <uint8_t bits>
SerialMux_<bits>::SerialMux_(Stream& serial) {
serial_ = &serial;
}

template <uint8_t bits>
SerialMux_<bits>::~SerialMux_() {
delete[] buffer_;
}
template <uint8_t maxPorts, uint8_t bits>
SerialMux_<maxPorts, bits>::SerialMux_(Stream& serial) : serial_ {&serial} {}


template <uint8_t bits>
uint8_t SerialMux_<bits>::add() {
Buffer<bits>* newBuffer {new Buffer<bits>[++ports_]};
memcpy(newBuffer, buffer_, (ports_ - 1) * sizeof(Buffer<bits>));
delete[] buffer_;
buffer_ = newBuffer;
template <uint8_t maxPorts, uint8_t bits>
uint8_t SerialMux_<maxPorts, bits>::add(Buffer<bits>* buffer) {
buffer_[ports_++] = buffer;
return ports_ - 1;
}


template <uint8_t bits>
size_t SerialMux_<bits>::available(uint8_t const port) {
update_();
return buffer_[port].available();
}

template <uint8_t bits>
int SerialMux_<bits>::read(uint8_t const port) {
update_();
return buffer_[port].read();
}

template <uint8_t bits>
void SerialMux_<bits>::write(uint8_t const port, uint8_t const data) {
update_();
template <uint8_t maxPorts, uint8_t bits>
void SerialMux_<maxPorts, bits>::write(
uint8_t const port, uint8_t const data) {
write_(port, &data, 1);
}

template <uint8_t const bits>
int SerialMux_<bits>::peek(uint8_t const port) {
update_();
return buffer_[port].peek();
template <uint8_t maxPorts, uint8_t bits>
void SerialMux_<maxPorts, bits>::update() {
while (serial_->available()) {
uint8_t data {read_()};
if (data == escape_) {
uint8_t port {read_()};
if (port != escape_) {
portRx_ = port;
continue;
}
}
if (portRx_ == controlPort_) {
control_(data);
return;
}
buffer_[portRx_]->write(data);
}
}


/* Control command handling. */
template <uint8_t bits>
void SerialMux_<bits>::control_(uint8_t const data) {
template <uint8_t maxPorts, uint8_t bits>
void SerialMux_<maxPorts, bits>::control_(uint8_t const data) {
switch (static_cast<Command>(data)) {
case protocol:
write_(controlPort_, protocol_, sizeof(protocol_));
Expand All @@ -157,39 +114,16 @@ void SerialMux_<bits>::control_(uint8_t const data) {
case reset:
break;
}
uint8_t const data_ {0};
write_(controlPort_, &data_, 1);
}

/*
* Send incoming data to virtual serial ports.
*/
template <uint8_t bits>
void SerialMux_<bits>::update_() {
while (serial_->available()) {
uint8_t data {read_()};
if (data == escape_) {
uint8_t port {read_()};
if (port != escape_) {
portRx_ = port;
continue;
}
}
if (portRx_ == controlPort_) {
control_(data);
return;
}
buffer_[portRx_].write(data);
}
write(controlPort_, 0);
}

/*
* Blocking read.
*
* \return The first byte of incoming data.
*/
template <uint8_t bits>
uint8_t SerialMux_<bits>::read_() const {
template <uint8_t maxPorts, uint8_t bits>
uint8_t SerialMux_<maxPorts, bits>::read_() const {
while (!serial_->available());
return serial_->read();
}
Expand All @@ -202,8 +136,8 @@ uint8_t SerialMux_<bits>::read_() const {
*
* \return Number of bytes written.
*/
template <uint8_t bits>
void SerialMux_<bits>::write_(
template <uint8_t maxPorts, uint8_t bits>
void SerialMux_<maxPorts, bits>::write_(
uint8_t const port, uint8_t const* const data, uint8_t const size) {
if (enabled_ || port == controlPort_) {
if (port != portTx_) {
Expand Down
43 changes: 25 additions & 18 deletions src/vSerial.tcc
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
#pragma once

#include "buffer.tcc"
#include "serialMux.tcc"

/*! Virtual serial device.
*
* \tparam maxPorts Maximum number of virtual serial ports.
* \tparam bits Buffer size control (2^`bits`).
*/
template <uint8_t bits=6>
template <uint8_t maxPorts, uint8_t bits>
class VSerial_ : public Stream {
public:
/*! Create a virtual serial device.
*
* \param[in] mux Serial multiplexer.
*/
VSerial_(SerialMux_<bits>&);
VSerial_(SerialMux_<maxPorts, bits>& mux);


/*! Get the number of bytes available for reading.
Expand Down Expand Up @@ -44,35 +46,40 @@ public:
int peek();

private:
SerialMux_<bits>* mux_ {nullptr};
Buffer<bits> buffer_ {};
SerialMux_<maxPorts, bits>* mux_ {nullptr};
uint8_t port_ {0};
};

using VSerial = VSerial_<>; //!< Virtual serial device.
using VSerial = VSerial_<4, 6>; //!< Virtual serial device.


template <uint8_t bits>
VSerial_<bits>::VSerial_(SerialMux_<bits>& mux)
: mux_ {&mux}, port_ {mux.add()} {}
template <uint8_t maxPorts, uint8_t bits>
VSerial_<maxPorts, bits>::VSerial_(SerialMux_<maxPorts, bits>& mux)
: mux_ {&mux}, port_ {mux.add(&buffer_)} {}


template <uint8_t bits>
int VSerial_<bits>::available() {
return mux_->available(port_);
template <uint8_t maxPorts, uint8_t bits>
int VSerial_<maxPorts, bits>::available() {
mux_->update();
return buffer_.available();
}

template <uint8_t bits>
int VSerial_<bits>::read() {
return mux_->read(port_);
template <uint8_t maxPorts, uint8_t bits>
int VSerial_<maxPorts, bits>::read() {
mux_->update();
return buffer_.read();
}

template <uint8_t bits>
size_t VSerial_<bits>::write(uint8_t data) {
template <uint8_t maxPorts, uint8_t bits>
size_t VSerial_<maxPorts, bits>::write(uint8_t data) {
mux_->update();
mux_->write(port_, data);
return 1;
}

template <uint8_t bits>
int VSerial_<bits>::peek() {
return mux_->peek(port_);
template <uint8_t maxPorts, uint8_t bits>
int VSerial_<maxPorts, bits>::peek() {
mux_->update();
return buffer_.peek();
}
2 changes: 1 addition & 1 deletion tests/test_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "../src/buffer.tcc"

Buffer<6> buffer;
Buffer<6> buffer {};


TEST_CASE("Empty buffer", "[buffer][empty]") {
Expand Down
1 change: 1 addition & 0 deletions tests/test_lib.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#define CATCH_CONFIG_RUNNER

#include <catch.hpp>


Expand Down

0 comments on commit 8b91f47

Please sign in to comment.