diff --git a/adc/Makefile b/adc/Makefile
index 1380a0b..826e24e 100644
--- a/adc/Makefile
+++ b/adc/Makefile
@@ -17,7 +17,7 @@ DEL    = rm -f
 
 # zdrojaky
 OBJS   = main.o adcclass.o
-#OBJS  += usartclass.o print.o
+OBJS  += usartclass.o print.o
 
 include $(TARGET)/$(TOOL).mk
 BOBJS = $(addprefix $(BLD),$(OBJS))
diff --git a/adc/adcclass.cpp b/adc/adcclass.cpp
index 9a024e2..0868fd8 100644
--- a/adc/adcclass.cpp
+++ b/adc/adcclass.cpp
@@ -1,22 +1,14 @@
 #include "system.h"
 #include "oneway.h"
 #include "adcclass.h"
-#include "gpio.h"
-
-static GpioClass led (GPIOD, 4);
 
 static AdcClass * pInstance = nullptr;
 
-volatile unsigned gCount = 0u;
-
 extern "C" void DMA1_Channel1_IRQHandler( void ) __attribute__((interrupt));
 void DMA1_Channel1_IRQHandler( void ) {
   DMA1_Type::INTFR_DEF state (DMA1.INTFR);
   DMA1.INTFCR.R = state.R;  // clear all
   if (!pInstance) return;
-  gCount += 1u;
-  const bool b = (gCount & 1u) == 0u;
-  led << b;
   if      (state.B.HTIF1 != RESET) pInstance->send (false);
   else if (state.B.TCIF1 != RESET) pInstance->send (true);
 }
@@ -47,12 +39,16 @@ static inline void Timer2Init (uint32_t us) noexcept {
   TIM2.PSC.R    = 47u;          // 1 MHz Fs
   TIM2.ATRLR.R  = us - 1u;
   // TRGO update for ADC
-  TIM2.CTLR2.B.MMS  = 2;
+  TIM2.CTLR2.B.MMS = 2u;
 }
 static inline void AdcCalibrate (void) noexcept {
-  ADC1.RSQR3.B.SQ1    = 1u;    // CH1
+  // RESET
+  RCC.APB2PRSTR.B.ADC1RST = SET;
+  RCC.APB2PRSTR.B.ADC1RST = RESET;
+  // set channels
+  ADC1.RSQR3.B.SQ1    = 2u;    // CH2
   ADC1.RSQR1.B.L      = 0u;    // 1 regular conversion
-  ADC1.SAMPTR2_CHARGE2.B.SMP1_TKCG1 = 7u;
+  ADC1.SAMPTR2_CHARGE2.B.SMP2_TKCG2 = 7u;
   ADC1.CTLR1.B.SCAN   = SET;
   
   ADC1.CTLR2.B.ADON   = SET;
@@ -60,7 +56,6 @@ static inline void AdcCalibrate (void) noexcept {
   while (ADC1.CTLR2.B.RSTCAL != RESET);  // Wait until RSTCAL=0
   ADC1.CTLR2.B.CAL    = SET;             // Launch the calibration by setting CAL
   while (ADC1.CTLR2.B.CAL    != RESET);  // Wait until CAL=0  
-  ADC1.CTLR2.B.ADON   = RESET;
 }
 typedef __SIZE_TYPE__ size_t;
 static inline void Dma1Ch1Init (void * ptr) noexcept {
@@ -72,12 +67,14 @@ static inline void Dma1Ch1Init (void * ptr) noexcept {
   DMA1.CNTR1 .R = FULL_LEN;
   // Configure increment, size, interrupts and circular mode
   DMA1.CFGR1.modify([] (DMA1_Type::CFGR1_DEF & r) -> auto {
-    r.B.MINC  = SET;
-    r.B.MSIZE = 1u;
-    r.B.PSIZE = 1u;
-    r.B.HTIE  = SET;
-    r.B.TCIE  = SET;
-    r.B.CIRC  = SET;
+    r.B.PL      = 3u;       // highest priority
+    r.B.MEM2MEM = RESET;    // periferal -> memory
+    r.B.MINC    = SET;      // memory increment
+    r.B.MSIZE   = 1u;       // 16-bit
+    r.B.PSIZE   = 1u;       // 16-bit
+    r.B.HTIE    = SET;      // INT Enable HALF
+    r.B.TCIE    = SET;      // INT Enable FULL
+    r.B.CIRC    = SET;      // Circular MODE
     // Enable DMA Channel 1
     r.B.EN    = SET;
     return r.R;
@@ -87,13 +84,12 @@ static inline void AdcPostInit (void) noexcept {
   ADC1.CTLR2.modify([](ADC1_Type::CTLR2_DEF & r) -> auto {
     r.B.DMA     = SET;
     r.B.EXTTRIG = SET;
-    r.B.EXTSEL  = 3u;     // TRGO event of timer 2
+    r.B.EXTSEL  = 3u;       // TRGO event of timer 2
     r.B.SWSTART = SET;
-    r.B.ADON    = SET;
     return r.R;
   });
 }
-
+////////////////////////////////////////////////////////////////////////////////////
 AdcClass::AdcClass() noexcept : pL (buffer), pH (buffer + HALF_LEN), dst (nullptr) {
   pInstance = this;
   EnableClock ();
diff --git a/adc/main.cpp b/adc/main.cpp
index ffb9622..eb7a517 100644
--- a/adc/main.cpp
+++ b/adc/main.cpp
@@ -2,11 +2,49 @@
 #include "usartclass.h"
 #include "print.h"
 #include "adcclass.h"
+#include "oneway.h"
 //////////////////////////////////////
+class Process : public OneWay {
+  GpioClass         led;
+  UsartClass        serial;
+  Print             cout;
+  FIFO<uint16_t, 8> data;
+  int               pass_cnt;
+  public:
+    explicit Process () noexcept : OneWay (),
+      led (GPIOD, 4), serial (115200u), cout (DEC), data(), pass_cnt (0) {
+      cout += serial;
+    }
+    unsigned Send (uint16_t * const ptr, const unsigned len) override {
+      unsigned sum = 0u;
+      for (unsigned n=0; n<len; n++) sum += ptr [n];
+      sum >>= 4;
+      data.Write (static_cast<uint16_t> (sum));
+      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í 1kHz,
+ * 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;
 }
diff --git a/ch32v003/system.h b/ch32v003/system.h
index 2b340ca..566ae24 100644
--- a/ch32v003/system.h
+++ b/ch32v003/system.h
@@ -32,7 +32,7 @@ struct NVIC_Type {
       IRER [((uint32_t)(IRQ) >> 5)] = (1 << ((uint32_t)(IRQ) & 0x1F));
     }
 };
-NVIC_Type & NVIC = * reinterpret_cast<NVIC_Type * const> (0xE000E000);
+static NVIC_Type & NVIC = * reinterpret_cast<NVIC_Type * const> (0xE000E000);
 struct SysTick_Type {
   union CTLR_DEF  {
     struct {
@@ -68,6 +68,6 @@ struct SysTick_Type {
       NVIC.EnableIRQ (SysTicK_IRQn);
     }
 };
-SysTick_Type & SysTick = * reinterpret_cast<SysTick_Type * const> (0xE000F000);
+static SysTick_Type & SysTick = * reinterpret_cast<SysTick_Type * const> (0xE000F000);
 
 #endif // SYSTEM_H