#include "gpio.h"
#include "usartclass.h"
#include "print.h"
#include "adcclass.h"
#include "oneway.h"
static constexpr int ISHIFT = 12;
//////////////////////////////////////
class Process : public OneWay {
  GpioClass     led;
  UsartClass    serial;
  Print         cout;
  FIFO<int, 8>  data;
  const int     coeff, trigger;
  public:
    explicit Process () noexcept : OneWay (),
      led (GPIOD, 4), serial (115200u), cout (DEC), data(), coeff (1706), trigger (0x1000) {

      cout += serial;
    }
    unsigned Send (uint16_t * const ptr, const unsigned len) override {
      int q2 = 0, q1 = 0;
      for (unsigned n=0; n<len; n++) {
        // Vlastní Goertzelův algoritmus.
        int q0 = coeff * q1;
        // pokud byl coeff zvětšen, je třeba to tu zase zmenšit
        q0 >>= ISHIFT;                        // zmenšení pro int
        q0  += ((int) ptr [n]) - q2;          // vlastní výpočet
        q2   = q1;                            // posuv o vzorek
        q1   = q0;                            // (rekurze)
      }
      int rv = q1 * q2;
      rv  *= -coeff;
      rv >>= ISHIFT;              // tady nutno zmenšit tak, jak bylo zvětšeno v calc_coeff()
      rv  += q1 * q1 + q2 * q2;   // výkon by byl sqrt (rv), není nutné počítat, napětí stačí
      data.Write (rv);            // dáme do FIFO, vybíráme v main()
      q1 = 0; q2 = 0;
      return len;
    }
    void pass () {
      int avg;
      if (!data.Read (avg)) return;
      cout << avg << EOL;
      if (avg > trigger) led << true;
      else               led << false;
    }
};
//////////////////////////////////////
static AdcClass adc;
static Process  out;
int main () {
  adc.attach(out);
  for (;;) {
    out.pass();
  }
  return 0;
}