Program Listing for File terminal_serial.hpp

Return to documentation for file (src/tap/communication/serial/terminal_serial.hpp)

/*
 * Copyright (c) 2020-2021 Advanced Robotics at the University of Washington <robomstr@uw.edu>
 *
 * This file is part of Taproot.
 *
 * Taproot is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Taproot 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Taproot.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef TAPROOT_TERMINAL_SERIAL_HPP_
#define TAPROOT_TERMINAL_SERIAL_HPP_

#include <cstring>
#include <map>

#ifdef PLATFORM_HOSTED
#ifdef ENV_UNIT_TESTS
#include "tap/stub/terminal_device_stub.hpp"
#else
#include "hosted_terminal_device.hpp"
#endif  // ENV_UNIT_TESTS
#else
#include "uart_terminal_device.hpp"
#endif

#include "tap/architecture/periodic_timer.hpp"
#include "tap/board/board.hpp"
#include "tap/communication/serial/uart.hpp"
#include "tap/util_macros.hpp"

#include "modm/io.hpp"

namespace tap
{
class Drivers;
}

namespace tap::communication::serial
{
class TerminalSerialCallbackInterface
{
public:
    virtual bool terminalSerialCallback(
        char *inputLine,
        modm::IOStream &outputStream,
        bool streamingEnabled) = 0;

    virtual void terminalSerialStreamCallback(modm::IOStream &outputStream) = 0;
};  // class TerminalSerialCallbackInterface

class TerminalSerial
{
public:
    static constexpr char DELIMITERS[] = " \t";
    static constexpr int MAX_LINE_LENGTH = 256;
    static constexpr int STREAMING_PERIOD = 500;

    explicit TerminalSerial(Drivers *drivers);

    DISALLOW_COPY_AND_ASSIGN(TerminalSerial);

    virtual ~TerminalSerial() = default;

    mockable void initialize();

    mockable void update();

    mockable void addHeader(const char *header, TerminalSerialCallbackInterface *callback);

private:
    // Use either an IO device that interacts with UART or with stdin/stdout.
#ifdef PLATFORM_HOSTED
#ifdef ENV_UNIT_TESTS
public:
    stub::TerminalDeviceStub device;

private:
#else
    HostedTerminalDevice device;
#endif  // ENV_UNIT_TESTS
#else
    UartTerminalDevice device;
#endif

    modm::IOStream stream;

    char rxBuff[MAX_LINE_LENGTH];

    uint8_t currLineSize = 0;

    TerminalSerialCallbackInterface *currStreamer = nullptr;

    tap::arch::PeriodicMilliTimer streamingTimer;

    struct cmpByStringEquality
    {
        bool operator()(const char *c1, const char *c2) const { return strcmp(c1, c2) < 0; }
    };

    std::map<const char *, TerminalSerialCallbackInterface *, cmpByStringEquality>
        headerCallbackMap;

    Drivers *drivers;

    bool prevCharSpace = false;

    void printUsage();
};  // class TerminalSerial
}  // namespace tap::communication::serial

#endif  // TAPROOT_TERMINAL_SERIAL_HPP_