#ifndef SAMPLERING_H
#define SAMPLERING_H
#include <stdint.h>
#include "structures.h"
#include "baselayer.h"

static constexpr unsigned RING_BIT = 10;
static constexpr unsigned RING_LEN = 1u << RING_BIT;
static constexpr unsigned RING_MSK = RING_LEN - 1u;

static constexpr unsigned DATA_HALF_LEN = 1024u;
static constexpr unsigned DATA_FULL_LEN = DATA_HALF_LEN * 2u;

static constexpr unsigned RCVD_BUFLEN = 16;
enum RCVD_STATUS {
  RCVD_IDLE = 0,
  RCVD_DATA,
};

class SampleRing : public BaseLayer {
  [[gnu::aligned(4)]]DATA_BLOCK ring_buffer [RING_LEN];
  TrigerSettings                m_settings;
  volatile unsigned             m_head, m_tail;
  volatile unsigned             m_lenght;
  bool                          m_old_triger;
  bool                          m_trigered;
  volatile bool                 m_finished;
  TIME_BASE_MODE                m_mode, o_mode;
  
  [[gnu::aligned(4)]]char       rcvd_buffer [RCVD_BUFLEN];
  unsigned                      rcvd_counter;
  RCVD_STATUS                   rcvd_status;
  public:
    explicit SampleRing () noexcept : BaseLayer(), m_settings(), m_head(0), m_tail(0), m_lenght(0),
                                     m_old_triger(false), m_trigered(false), m_finished(false),
                                     m_mode (TIME_BASE_TRIGERED), o_mode (TIME_BASE_TRIGERED),
                                     rcvd_counter(0u), rcvd_status (RCVD_IDLE) {};
    uint32_t Up (const char * data, const uint32_t len) override;
    void write  (DATA_BLOCK const * data);
    void pass   ();
  protected:
    uint32_t BlockSend  (const char * buf,  const uint32_t len);
    uint32_t SendPrefix ();
    uint32_t SendData   (const DATA_BLOCK & data);
    bool read           (DATA_BLOCK & sample);
    void CmdReceived ();
    void CommandPass (const unsigned cmd);
    void ReloadTimer (const unsigned n);
};

#endif // SAMPLERING_H