/*
 * CDCCommandStream.cpp
 *
 *  Created on: 17 Jan 2020
 *      Author: andrewcapon
 */
#include "32blit.h"
#include "usbd_cdc_if.h"
#include "usbh_cdc.h"

extern USBD_HandleTypeDef hUsbDeviceHS;
extern USBH_HandleTypeDef hUsbHostHS;

#include "CDCCommandStream.h"

void CDCCommandStream::Init(void)
{
	m_state = stDetect;
	m_uHeaderScanPos = 0;
	m_bNeedsUSBResume = false;
}

void CDCCommandStream::AddCommandHandler(CDCCommandHandler::CDCFourCC uCommand, CDCCommandHandler *pCommandHandler)
{
	m_commandHandlers[uCommand] = pCommandHandler;
}


void CDCCommandStream::LogTimeTaken(CDCCommandHandler::StreamResult result, uint32_t uBytesHandled)
{
	// can be used to log time taken
}


void CDCCommandStream::Stream(void)
{
  static uint32_t uLastResumeTime = HAL_GetTick();

  if(m_bNeedsUSBResume) // FIFO Full, so empty and resume USB
  {
    while(CDCFifoElement *pElement = GetFifoReadElement())
    {
      if(pElement->m_uLen)
        Stream(pElement->m_data, pElement->m_uLen);
      ReleaseFifoReadElement();
    }
    m_bNeedsUSBResume = false;
	if(USB_GetMode(USB_OTG_HS))
	{
		USBH_CDC_Receive(&hUsbHostHS, GetFifoWriteBuffer(), 64);
	}
	else
	{
		USBD_CDC_SetRxBuffer(&hUsbDeviceHS, GetFifoWriteBuffer());
		USBD_CDC_ReceivePacket(&hUsbDeviceHS);
	}
    uLastResumeTime = HAL_GetTick();
  }
  else
  {
    if(HAL_GetTick() > uLastResumeTime + 10) // USB Stalled, empty FIFO
    {
      // empty fifo
      while(CDCFifoElement *pElement = GetFifoReadElement())
      {
        if(pElement->m_uLen)
          Stream(pElement->m_data, pElement->m_uLen);
        ReleaseFifoReadElement();
      }
    }
  }
}

uint8_t CDCCommandStream::Stream(uint8_t *data, uint32_t len)
{
	blit_disable_ADC();
	uint8_t   *pScanPos  = data;

  while(pScanPos < (data+len))
  {
    if(m_state == stDetect)
    {
      bool bHeaderFound = false;
      while ((!bHeaderFound) && (pScanPos < (data+len)))
      {
        if(*pScanPos == m_header[m_uHeaderScanPos])
        {
          if(m_uHeaderScanPos == 3)
          {
            // header found
            bHeaderFound = true;
            m_uHeaderScanPos = 0;
            m_uCommandScanPos = 0;
          }
          else
            m_uHeaderScanPos++;
        }
        else
        {
          m_uHeaderScanPos = 0;
          m_uCommandScanPos = 0;
        }
        pScanPos++;
      }

      if(bHeaderFound)
      {
        // next command byte could be in next call
        while((m_state == stDetect) && (m_uCommandScanPos < 4))
        {
          uint8_t  *pCommandByte = (uint8_t *)(&uCommand)+m_uCommandScanPos;
          if(pScanPos >= (data + len)) // rest in next packet
            m_state = stDetectCommandWord;
          else
          {
            *pCommandByte = *pScanPos++;
            if(m_uCommandScanPos == 3)
            {
              m_state = stDispatch;
            }
            m_uCommandScanPos++;
          }
        }
      }
    }
    else
    {
      if(m_state == stDetectCommandWord)
      {
        while(m_uCommandScanPos < 4)
        {
          uint8_t *pCommandByte = (uint8_t *)(&uCommand)+m_uCommandScanPos;
          *pCommandByte = *pScanPos++;
          m_uCommandScanPos++;
        }
        m_state = stDispatch;
      }
    }

    if(m_state == stDispatch)
    {
      m_uRetryCount = 0;
      m_uDispatchTime = HAL_GetTick();

      m_pCurrentCommandHandler = m_commandHandlers[uCommand];
      if(m_pCurrentCommandHandler)
      {
        if(m_pCurrentCommandHandler->StreamInit(uCommand)) {
          m_state = stProcessing;
          m_dataStream.Clear(); // make sure there isn't any leftover data in the buffer
        } else
        {
          m_state = stDetect;
          LogTimeTaken(CDCCommandHandler::srFinish, 0);
        }
      }
      else
        m_state = stDetect; // No handler go back to detect state
    }

    if(m_state == stProcessing)
    {
      auto added_len = len - (pScanPos - data);

      m_dataStream.AddData(pScanPos, added_len);
      CDCCommandHandler::StreamResult result = m_pCurrentCommandHandler->StreamData(m_dataStream);

      switch(result)
      {
        case CDCCommandHandler::srError:
        case CDCCommandHandler::srFinish:
        {
          // handler has finished or failed go back to detect state
          m_state = stDetect;
          LogTimeTaken(result, m_pCurrentCommandHandler->GetBytesHandled());
          blit_enable_ADC();
        }
        break;

        case CDCCommandHandler::srNeedData:
          m_uRetryCount++;
          if(m_uRetryCount > 1)
          {
            m_state = stDetect;
            LogTimeTaken(result, m_pCurrentCommandHandler->GetBytesHandled());
            blit_enable_ADC();
          }
        return false;

        case CDCCommandHandler::srContinue:
        break;
      }

      // handled all data or need more
      if(m_dataStream.GetStreamLength() == 0 || m_state != stDetect)
        break;
      else // some data left, advance scan pos and try again
        pScanPos += added_len - std::min(added_len, m_dataStream.GetStreamLength());
    }

  }

	return m_state != stDetect;
}

uint32_t CDCCommandStream::GetTimeTaken(void)
{
	return HAL_GetTick() - m_uDispatchTime;
}


uint8_t	*CDCCommandStream::GetFifoWriteBuffer(void)
{
	uint8_t *pData = NULL;
	if(m_uFifoUsedCount < CDC_FIFO_BUFFERS - 1)
	{
		pData = m_fifoElements[m_uFifoWritePos].m_data;
	}
	else
		m_bNeedsUSBResume = true;

	return pData;
}

void	CDCCommandStream::ReleaseFifoWriteBuffer(uint8_t uLen)
{
	m_fifoElements[m_uFifoWritePos].m_uLen = uLen;
	m_uFifoWritePos++;
	if(m_uFifoWritePos == CDC_FIFO_BUFFERS)
		m_uFifoWritePos = 0;
	m_uFifoUsedCount++;
}

CDCFifoElement  *CDCCommandStream::GetFifoReadElement(void)
{
	CDCFifoElement *pElement = NULL;
	if(m_uFifoUsedCount)
		pElement = &m_fifoElements[m_uFifoReadPos];
	return pElement;
}

void CDCCommandStream::ReleaseFifoReadElement(void)
{
	m_uFifoReadPos++;
	if(m_uFifoReadPos == CDC_FIFO_BUFFERS)
		m_uFifoReadPos = 0;
	m_uFifoUsedCount--;
}

// usb host glue
extern CDCCommandStream g_commandStream;

void USBH_CDC_ReceiveCallback(USBH_HandleTypeDef *phost)
{
  	g_commandStream.ReleaseFifoWriteBuffer(USBH_CDC_GetLastReceivedDataSize(phost));

	// If a new writebuffer is available, set RxBuffer and requext next USB packet
	if(uint8_t *pBuffer = g_commandStream.GetFifoWriteBuffer())
    	USBH_CDC_Receive(phost, pBuffer, 64);
}

extern "C" void usb_host_ready(USBH_HandleTypeDef *phost) {
	if(uint8_t *pBuffer = g_commandStream.GetFifoWriteBuffer())
    	USBH_CDC_Receive(phost, pBuffer, 64);
}
