
/*
  USBSerial.h

  Copyright (c) 2023, Magawin
  Original code (pre-library): Copyright (c) 2011, Peter Barrett

  This library 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 2.1 of the License, or (at your option) any later version.

  This library 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 library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef   _USBSERIAL_H_
#define   _USBSERIAL_H_


#include <Arduino.h>

#if !defined(USBCON)   // || !defined(USBD_USE_HID_COMPOSITE)

#error "USB HID not enabled! Select 'HID' in the 'Tools->USB interface' menu."

#else

//================================================================================

#define    EP0_PACKET_SIZE        8                                       //// Maximum packet size for EP0.
#define    EP1_PACKET_SIZE        64                                      //// Maximum packet size for EP1.
#define    EP2_PACKET_SIZE        64                                      //// Maximum packet size for EP2.
#define    EP3_PACKET_SIZE        64                                      //// Maximum packet size for EP3.



#ifdef __cplusplus

#include "Stream.h"
#include "chip.h"

#include "USBSerial_API.h"
#include "MG32x02z_USBD_API.h"



#ifdef SERIAL_BUFFER_SIZE
#undef SERIAL_BUFFER_SIZE
#endif


#define COM_STATUS_EP                      USB_EP1                       ////< COM STATUS Endpoint.
#define COM_DATAUPSTREAM_EP                USB_EP2                       ////< COM upstream data Endpoint.
#define COM_DATADOWNSTREAM_EP              USB_EP3                       ////< COM downstream data Endpoint.



#define COM_DATAUPSTREAM_DATASIZE          EP2_PACKET_SIZE               ///< COM upstream MAX. data size.
#define COM_DATAUPSTREAM_BUFFER_SIZE       EP2_PACKET_SIZE               ///< MAX size for COM upstream software buffer.
#define COM_DATADOWNSTREAM_BUFFER_SIZE     EP3_PACKET_SIZE               ///< MAX size for COM downstream software buffer.

#define SERIAL_BUFFER_SIZE  COM_DATADOWNSTREAM_BUFFER_SIZE

//class USBSerial_ : public Stream
class USBSerial_ : public HardwareSerial
{
public:
    USBSerial_( USB_EP_Struct*  pStatusEP,  
                USB_EP_Struct*  pDataUpStreamEP, 
                USB_EP_Struct*  pDataDownStreamEP   );
                
private:
    USB_EP_Struct*    m_StatusEP;
    USB_EP_Struct*    m_DataUpStreamEP;
    USB_EP_Struct*    m_DataDownStreamEP;
    uint8_t           m_Protocol;

    COM_TypeDef*      m_pUsbCom;
    uint32_t          m_UsbComErrorCode;

private:
    uint16_t        m_available;
    uint8_t         m_UsbWriteBuf[COM_DATAUPSTREAM_BUFFER_SIZE];

    uint8_t         m_UsbReadBuf[SERIAL_BUFFER_SIZE];
    uint8_t         m_UsbRead_In;
    uint8_t         m_UsbRead_Out;
    uint8_t         m_UsbRead_Cnt;

    void DealUARTState(void);
    void Parameter_DeInit(void);

public:
    uint32_t SetLineCoding(uint8_t* sLineCodingBuf);
    void GetLineCoding(uint8_t* gLineCodingBuf);
    void SetControlLineState(uint8_t* sControlLineStateBuf);
    void SendBreak(uint8_t* SendBreakBuf);
    void ReceiveDownstreamData(void);
    
    void SetUARTState(void);
    

public:
    void begin(void);
    virtual void begin( unsigned long baudRate );
    virtual void end(void);


    virtual int available(void);
    int availableForWrite(void);
    virtual int peek(void);
    virtual int read(void);
    virtual void flush(void);

    virtual size_t write(uint8_t *buffer, size_t size) { return write((const uint8_t *)buffer, size); };

    virtual size_t write(uint8_t data);
    virtual size_t write(const uint8_t *buffer, size_t size);
    size_t writex(const uint8_t *buffer, size_t size);

    virtual size_t write(const char *buffer, size_t size)
    {
      return write((const uint8_t *)buffer, size);
    }

    size_t write(const char *str)
    {
        if (str == NULL)
        {
            return 0;
        }
        
        return write((const uint8_t *)str, strlen(str));
    }

    int printHex(  uint8_t uc_data   );
    int printHex(  uint16_t uc_data  );
    int printHex(  uint32_t uc_data  );
    
    int printHex(  int      data   ){ return printHex((uint32_t)data); }
    int printHex(  int8_t   data   ){ return printHex((uint8_t)data);  }
    int printHex(  int16_t  data   ){ return printHex((uint16_t)data); }
    int printHex(  int32_t  data   ){ return printHex((uint8_t)data);  }

    int printDec(uint32_t uc_data );

    //void IrqTransHandler(void) {;};
    //void IrqRecvHandler(void) {;};

    virtual operator bool() { return true; }
    


};




extern USBSerial_ USBSerial;




#endif  // #ifdef __cplusplus


#ifdef __cplusplus

#endif  // #ifdef __cplusplus


#ifdef __cplusplus
 extern "C" {
#endif




#ifdef __cplusplus
}
#endif




#endif




#endif

