#ifndef HDO_H
#define HDO_H
#include "gpio.h"
#include "usart.h"
#include "print.h"
#include "oneway.h"
#include "config.h"

static constexpr int ISHIFT = 12;
/* Tady je ten výpočet proveden externě.
static constexpr int calc_coeff (const double nfreq) {
  return lround (double(2UL << ISHIFT) * cos (2.0 * 3.14159265358979323846 * nfreq));
}
  coeff = calc_coeff (216.6 / 1000.0) = 1706
*/
/**
\enum stat
Stavy konečného automatu vyhodnocení telegramu
*/
enum stat {
  WAIT_FOR_BEGIN = 0,   //!< čekání na začátek telegramu
  SYNC_PULSE,           //!< startovací puls probíhá
  SYNC_SPACE,           //!< synchronizační mezera probíhá
  CORELATE,             //!< datový puls probíhá
};
static constexpr int SYNC_HI =  17;  //!< 2.33 sec délka startovacího pulsu
static constexpr int SYNC_LO =  22;  //!< 2.99 sec délka synchronizační mezery
static constexpr int TBUFLEN =  64;

class Hdo : public OneWay {
  GpioClass     led, relay;
  Usart         serial;
  Print         cout;
  FIFO<int, 8>  data;
  const int     coeff;
  const int     trigger;        //!< rozhodovací úroveň (napevno)
  const char *  cmd;            //!< rozhodovací, řídící string
  
  char      buf1[TBUFLEN];
  char      buf2[TBUFLEN];
  int       suma;
  uint32_t  bits;
  int       counter;            //!< čítač period
  stat      status;             //!< stav konečného automatu detekce
  
  public:
    explicit Hdo (const char * command) noexcept : OneWay (),
      led (LED_CFG), relay (REL_CFG), serial (115200u), cout (DEC), data(), coeff (1706), trigger (0x4000),
      cmd (command), suma (0), bits (0), counter (0), status (WAIT_FOR_BEGIN) {
        /* trigger musí být nastaven tak do 1/3 až do 1/2 maximální vyhodnocené hodnoty (viz výpis)
         * Je nutné použít HSE, tj. krystal 24 HHz. Bez toho to fakt nechodí a to i na procesorech i.e. STM.
         * */
      cout += serial;
      led  << true;
    }
    unsigned Send (uint16_t * const ptr, const unsigned len) override;
    void     pass ();
  protected:
    int  Decode    (int num, char * str);
    void HumanRead (const char * src, char * dst);
    int  Action    (char * tlg, const char * command);
};

#endif // HDO_H