/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef INCLUDE_ECXX_PLATFORM_SPECIFIC_VIRTUAL_UART_H
#error "this file cannot be included directly"
#endif
#undef INCLUDE_ECXX_PLATFORM_SPECIFIC_VIRTUAL_UART_H


#ifndef ECXX_PLATFORM_AVR_VIRTUAL_VIRTUAL_UART_H
#define ECXX_PLATFORM_AVR_VIRTUAL_VIRTUAL_UART_H


//
// Uncomment this to make the virtual UART can write-back the settings that was set by the host PC
//
// #define ECXX_AVR_VUART_DUMP_SETTINGS


namespace eCxx {


//
// A simple AVR VirtualUART wrapper
//
// WARNING : All functions derived from BasicOutputWriter<T> that accept parameters with data types
//           'PGMCharPointer' and 'PGMCharPointerFar' expect the pointers to come from program
//           memory exclusively!
//
// NOTE    : Whenever possible, use the versions that accept near program pointers because those that
//           accept the far program pointers may have more overhead and restrictions.
//
class VirtualUART : public BasicOutputWriter<VirtualUART> {
    public:
        using DataFormat = UART::DataFormat;

    public:
        inline ~VirtualUART() = default;

    public:
        VirtualUART(uint8_t ifNumber);

        void begin(uint32_t baudrate, DataFormat dataFormat = DataFormat::_8N1);
        void end();

        bool canRead() const;
        bool read(uint8_t& value);
        bool peek(uint8_t& value) const;

        bool canWrite() const;
        bool write(uint8_t value);
        void flush();

        uint16_t read(void* buffer, uint16_t size, uint16_t timeoutMS = 1000);
        uint16_t write(const void* buffer, uint16_t size);

#ifdef ECXX_AVR_VUART_DUMP_SETTINGS
        void _dumpSettings();
#endif

    private:
        uint8_t _ifNumber;

        bool    _prevTimeout;
        int16_t _peekBuff;

    private:
        void discardRXBuffer();
};


} // namespace eCxx


#endif
