/* VectorNav HSI Calibration Library v1.0.0.2
 *
 * Copyright (c) 2018 VectorNav Technologies, LLC
 *
 * This source code is proprietary to and copyrighted by VectorNav Technologies, LLC and is
 * available solely under license from VectorNav. All rights reserved. If you do not have a
 * license to use this source code from VectorNav, any use hereof is strictly prohibited by
 * U.S. law and other applicable law. This source code is restricted for use solely with the
 * products of VectorNav and as otherwise set forth in any agreement with VectorNav. Any
 * disclosure of this source code to the public or to any third party is also prohibited.
 */
#ifndef VNUPACKF_H_INCLUDED
#define VNUPACKF_H_INCLUDED

#include "vnupack.h"

#ifndef VNUART_PROTOCOL_BUFFER_SIZE
  /** Default internal buffers size for handling received UART data. */
  #define VNUART_PROTOCOL_BUFFER_SIZE 256
#endif

#ifdef __cplusplus
extern "C" {
#endif

/** \brief Defines signature of functions that can handle callback
*  notifications of packets successfully received and validated from a
*  VectorNav sensor. */
typedef void(*VnUartPacketFinder_PacketFoundHandler)(void *userData, struct VnUartPacket* packet, size_t runningIndexOfPacketStart);

#if defined(_MSC_VER)
  #pragma warning(push)
  #pragma warning(disable:4820)   /* Not concerned with tight data structure packing on Windows. */
#endif

/** \brief Data structure holding current parsing status of data received from
 *  a VectorNav sensor.
 *
 * This structure contains a buffer which will hold bytes that are currently
 * being processed. The size of this buffer can be adjusted by defining the
 * size using the preprocesser. For example, the size can be adjusted to use
 * 1024 bytes by defining VNUART_PROTOCOL_BUFFER_SIZE=1024. */
struct VnUartPacketFinder
{
  /** \brief Callback for when a packet has been found and validated. */
  VnUartPacketFinder_PacketFoundHandler packetFoundHandler;

  /** \brief User data for callbacks on the packetFoundHandler. */
  void *packetFoundHandlerUserData;

  /** \brief Used for correlating the position in the received raw data
  *   stream where packets are found.  */
  size_t runningDataIndex;

  /** \brief Indicates if an ASCII packet is currently being built. */
  bool asciiCurrentlyBuildingPacket;

  /** \brief Indicates a suspected start of an ASCII packet. */
  size_t asciiPossibleStartOfPacketIndex;

  /** \brief Index of start of ASCII packet in total running index. */
  size_t asciiRunningDataIndexOfStart;

  /** \brief Indicates if the first ending character has been found. */
  bool asciiEndChar1Found;

  /** \brief Indicates if we are currently building a binary packet. */
  bool binaryCurrentlyBuildingBinaryPacket;

  /** \brief Index of start of binary packet in total running index. */
  size_t binaryRunningDataIndexOfStart;

  /** \brief Holds the size of the receive buffer. */
  size_t bufferSize;

  /** \brief The current location to append data into the buffer. */
  size_t bufferAppendLocation;

  /** \brief Indicates if we have found the groups present data field for a
   *  binary packet we are building. */
  bool binaryGroupsPresentFound;

  /** \brief The groups present found from a binary packet. */
  uint8_t binaryGroupsPresent;

  /** \brief Indicates the number of bytes remaining to have all group fields
   *  for a binary data packet we are processing. */
  uint8_t binaryNumOfBytesRemainingToHaveAllGroupFields;

  /** \brief Start index of a possible binary packet. */
  size_t binaryPossibleStartIndex;

  /** \brief Keeps track of the number of bytes remaining for a complete
   *  binary packet. */
  size_t binaryNumberOfBytesRemainingForCompletePacket;

  /** \brief The receive buffer. */
  uint8_t receiveBuffer[VNUART_PROTOCOL_BUFFER_SIZE];

};

#if defined(_MSC_VER)
  #pragma warning(pop)
#endif

#ifndef __cplusplus
typedef struct VnUartPacketFinder VnUartPacketFinder_t;
#endif

/** \brief Initializes the VnUartPacketFinder data structure.
* \param[in] pf VnUartPacketFinder to init. */
void
VnUartPacketFinder_initialize(
    struct VnUartPacketFinder* pf);

/** \brief Processes received data from the UART.
* \param[in] finder The associated VnUartPacketFinder containing the data
*     processing state.
* \param[in] data The received data.
* \param[in] len The number of bytes to process. */
enum VnError
VnUartPacketFinder_processData(
    struct VnUartPacketFinder* finder,
    uint8_t* data,
    size_t len);

/** \brief Allows registering for notification of when valid packets are found.
 * \param[in] handler The callback function for receiving notifications.
 * \param[in] userData Pointer to user supplied data which will be sent on all callback notifications.
 * \return Any errors encountered. */
enum VnError
VnUartPacketFinder_registerPacketFoundHandler(
    struct VnUartPacketFinder* finder,
    VnUartPacketFinder_PacketFoundHandler handler,
    void *userData);

#ifdef __cplusplus
}
#endif

#endif
