#include "gpio.h"
#include "usart.h"
#include "print.h"
#include "adcclass.h"
#include "oneway.h"
//////////////////////////////////////
class Process : public OneWay {
  GpioClass         led;
  Usart             serial;
  Print             cout;
  FIFO<uint16_t, 8> data;
  int               pass_cnt;
  unsigned          average;
  public:
    explicit Process () noexcept : OneWay (),
      led (GPIOD, 4), serial (115200u), cout (DEC), data(), pass_cnt (0), average (0u) {
      cout += serial;
    }
    unsigned Send (uint16_t * const ptr, const unsigned len) override {
      // Klouzavý průměr s exponenciálním zapomínáním lépe drží stálou hodnotu pro zobrazení.
      // Průměr je rozšířen na 12-bit (0 - 4096) násobením hodnoty 4.
      for (unsigned n=0; n<len; n++) average = (15u * average + 4u * ptr [n]) >> 4;
      data.Write (static_cast<uint16_t> (average));
      return len;
    }
    void pass () {
      uint16_t avg;
      if (!data.Read (avg)) return;
      cout << "pass: " << pass_cnt << ", avg = " << static_cast<int>(avg) << EOL;
      pass_cnt += 1;
      const bool b = pass_cnt & 1;
      led << b;
    }
};
//////////////////////////////////////
/* Tohle DEMO je složitější. ADC má
 * pevnou frekvenci vzorkování 10kHz,
 * vzorky se průměrují v přerušení a
 * vypisují (v jiném přerušení) na
 * sériový port.
 * */
//////////////////////////////////////
static AdcClass adc;
static Process  out;
int main () {
  adc.attach(out);
  for (;;) {
    out.pass();
  }
  return 0;
}