@startuml
title Dekodovanie UART: decode_uart_samples

start

:Inicializacia out (Vec<u8, 256>) a idx = 0;

:nbits = cfg.data_bits;
:ovs = oversample;

:parity_bits = 0 alebo 1 podla cfg.parity;
:stop_bits_count = 1 alebo 2 podla cfg.stop_bits;

:frame_bits = 1 + nbits + parity_bits + stop_bits_count;
:frame_len = frame_bits * ovs;

while (idx + frame_len <= samples.len()?) is (ano)
  if (Start bit detekovany?\n(samples[idx] != 0 && samples[idx + 1] == 0)) then (ano)
    :center_offset = ovs / 2;
    :scan_idx = idx + center_offset;

    if (get_bit(scan_idx) == 0?\nvalidacia START bitu) then (ano)
      :scan_idx += ovs\n(posun na prvy data bit);
      :data = 0;

      repeat :Citanie datovych bitov (0..nbits-1, LSB first)
        if (get_bit(scan_idx) == 1?) then (ano)
          :data |= 1 << bit;
        endif
        :scan_idx += ovs;
      repeat while (zvysne data bity?) is (ano)
      ->nie;

      :error_data = false;

      if (cfg.parity != Parity::None?) then (ano)
        :expected_parity = calculate_parity(data, cfg.parity);
        :actual_parity = get_bit(scan_idx);
        if (expected_parity != actual_parity?) then (ano)
          :error_data = true;
          note right: Chyba parity
        endif
        :scan_idx += ovs;
      endif

      repeat :Kontrola stop bitov
        if (get_bit(scan_idx) == 0?) then (ano)
          :error_data = true;
          note right: Framing chyba (stop bit = 0)
          break
        endif
        :scan_idx += ovs;
      repeat while (zvysne stop bity?) is (ano)
      ->nie;

      if (error_data?) then (ano)
        :idx += 1;\n(preskoc chybny frame);
      else (nie)
        :push data do out;
        :idx = scan_idx;

        :Preskoc idle HIGH (hladanie dalsieho start bitu);
        while (idx < samples.len() && samples[idx] != 0?) is (ano)
          :idx += 1;
        endwhile (nie)

        if (idx > 0?) then (ano)
          :idx -= 1;\n("mensi hack");
        endif
      endif
    else (nie)
      :idx += 1;\n(falosny start);
    endif
  else (nie)
    :idx += 1;
  endif
endwhile (nie)

:Navrat (out, idx);

stop
@enduml
