Kho tháng 1/2019
Mon Jan 7 07:25:29 +07 2019
Antenna Calibration tập hai
... tiếp tục từ tập một ...
OK. Giả định gửi và nhận một Z-C sequence equation/block ra ngoài trên năm tần số ("frequency bin") khác nhau. Sau khi tính toán xong, ta có năm độ lệch pha (nói cách khác, năm độ lệch về thời gian). Nhưng mà ở time domain, lệch năm cái làm sao xử lý? Năm tần số chuyển qua time domain chỉ còn là một, và phải chỉ có một độ lệch (theo thời gian).
Cách dễ nhất có lẽ là cứ lấy trung bình độ lệch pha trên tất cả các tần số (frequency bin). Nhưng làm vậy không đúng bởi vì độ trễ theo thời gian phụ thuộc vào pha và tần số.
Để dễ hình dung, có thể xem video clip này
để thấy cách biểu diễn của sóng của tần số với số phức. Tần số sẽ quyết định tốc độ quay của trục đó. Giờ hình dung tín hiệu gửi bao gồm hai sóng sin
exp(x * i) + exp(x * 2i)
Đồ thị của tín hiệu này với x từ 0 đến 3π/2 (đường cong cong màu tím), kèm theo pha của hai tần số bên trong (vàng và đỏ) giống như vầy:
Giả định tín nhiệu nhận vào là ở thời điểm 3π/2 (cuối trục X). Độ lệch pha (so với x=0) của hai tần số (hai đường đỏ và vàng) sẽ là -π/2 và π. Nhưng để ý là pha quay vòng từ -π đến π xong lại về -π, hai đường này hiện zigzac và tín độ lệch theo thời gian sẽ không đúng vì độ dài nó "quay" (theo cái video clip) dài hơn nhiều. Độ dài "đúng đắn" là hai cái đường xanh lá và lục, với giá trị là 3π/2 và 3π (là giá trị gốc cộng thêm 2π)
Cái giá trị tính được là cái ở đường vàng và đỏ. Nhưng cái giá trị phản ánh đúng độ lệch thời gian là đường xanh và lục. Việc chuyển đổi này gọi là unwrap phase.
Trong trường hợp lý tưởng, tất cả các điểm trên cái đồ thị trên sẽ
khớp chính xác một đường thẳng y(x) = ax + b
. Trên thực tế, bởi vì
nhiễu và mấy cái lăng nhăng, một vài điểm sẽ hơi lệch khỏi đường thẳng
ảo này. Tuy nhiên ta vẫn có thể ước lượng tham số cho đường thẳng này
(linear fit).
Khoảng cách (theo radian sau khi unwrap) giữa tần số đầu và cuối là "phase slope". Độ lệch theo thời gian là
delay = (Ts * PhaseSlope) / 2π (Ts = sampling rate)
(Ghi chú, linear fit hoặc polynomial fit là cách ước lượng một hàm số
với N tham số khớp nhất với một tập điểm cho trước. Với linear fit,
chỉ có hai tham số, vd a
và b
trong y(x) = ax + b
. Nth order
polynomial fit dùng hàm số phức tạp hơn, vd 2nd order là
y(x) = ax^2 + bx + c
... Xem taylor polynomial
để biết cách tính những tham số này)
Trong trường hợp tín hiệu nhận bị nhiễu nặng nề, hoặc chụp "nhầm" (vd nhầm thời điểm, hoặc phần cứng nhận tín hiệu bị lỗi...), ta có thể loại ngay những tín hiệu dỏm bằng cách tính MSE (Mean Square Error). MSE tính theo độ lệch giữa tập điểm thực và đường "linear fit" tính được. Nếu MSE quá cao, ta coi tín hiệu nhận là dỏm và bỏ. (Trong một số trường hợp, thay vì dùng tập điểm thực để so sánh với linear fit, 5th order polynomial fit được dùng, nhưng không hiểu tại sao, có thể tại vì độ lệch pha tại những tần số đáng quan tâm không có trong tập điểm gốc nên phải nội suy với polynomial?).
Có một mớ cái lăng nhăng khác cải thiện tình hình khi xử lý nhiều nhánh ănten (đặc biệt là khi một vài nhánh bị hư). Nếu loại hết mấy cái đó ra thì ta đã có độ lệch pha của từng nhánh. Vấn đề cuối cùng là làm sao xài cái này.
Nếu FIR được dùng để điều chỉnh pha thì ta có thể tính polynomial fit cho độ lệch pha của một nhánh ănten (trên tất cả tần số), xong nội suy N taps cho FIR. Xong! Một trong những đặc điểm của FIR là làm lệch pha của tín hiệu nó xử lý. Nếu tính toán hệ số FIR đúng, kết quả chạy qua FIR sẽ bị điều chỉnh pha (vừa đủ để bù đắp cho phần lệch bởi phần cứng/môi trường) để tất cả các ăn ten gửi ra cùng thời điểm.
Nếu điều chỉnh pha trong frequency domain (vd baseband) thì mọi chuyện còn dễ hơn. Công thức Euler có thể được dùng để chỉnh pha. Cái hấp dẫn hơn khi "bỳ đắp" pha trong frequency domain là khi độ lệch pha lớn hơn 2π...
Cập nhật 2 lần. Lần cuối: Tue Jan 08 03:34:03+0011 2019
Fri Jan 4 14:37:45 +07 2019
Linux Desktop -- bỏ phố dzìa quê lên núi
GNOME ngày càng nản. KDE ngày càng nặng. Quay về với Fluxbox.
Tập một, dĩ nhiên là cài fluxbox và đồ phụ tùng
emerge fluxbox xset setxkbmap xkill xlsfonts xrandr xsetroot \
rxvt-unicode dunst imagemagick tinynotify-send
Chỉnh hệ thống để startx
mặc định chạy fluxbox
echo XSESSION=fluxbox >/etc/env.d/99xsession
env-update
Bi nhiêu đây là đủ để chạy startx
(cần useflag elogind để chạy X
không cần root, nhưng bản thân elogind thì không cần useflag polkit).
Thằng này chạy hết script trong /etc/X11/xinit/xinitrc.d
và chạy
startfluxbox
. Thằng này sẽ exec ~/.fluxbox/startup
nếu có. OK khởi
động hết mấy thứ cần thiết:
mkdir ~/.fluxbox
cat >~/.fluxbox/startup <<EOF
xset +fp /usr/share/fonts/terpinus
#setxkbmap -option ctrl:nocaps
# xrandr --output HDMI-1 --auto --output eDP-1 --off
# redshift ...
export GTK_IM_MODULE=xim
export XMODIFIERS=@im=ibus
export QT_IM_MODULE=ibus
IBUS_ENABLE_SYNC_MODE=0 ibus-daemon -drx
display -window root -sample 1080 -backdrop ~/u/fondo1p.jpg
gkrellm&
urxvt&
exec fluxbox
EOF
chmod u+x ~/.fluxbox/startup
Tạo /etc/X11/xorg.conf
để chứa các thông tin cấu hình
Ctrl-Alt-Backspace và dùng CapsLock như Ctrl:
Section "ServerFlags"
Option "DontZap" "false"
EndSection
Section "InputClass"
Identifier "Keyboard Defaults"
MatchIsKeyboard "yes"
Option "XkbOptions" "terminate:ctrl_alt_bksp,ctrl:nocaps"
EndSection
Tạo /etc/security/limits.d/99-esync.conf
để bảo đảm proton esync
chạy OK:
pclouds - nofile 1048576
(Một số gói bổ sung cho cái script trên bao gồm terpinus, redshift, ibus-m17n, imagemagick, gkrellm, rofi, docker, wmCalClock và iwd)
Cần bảo đảm fluxbox style không đặt ảnh nền, và tiện tay chỉnh kích thước phông chữ luôn
cat >~/.fluxbox/overlay <<EOF
background: unset
*.font: sans-12
EOF
echo "sessions.styleOverlay: $HOME/.fluxbox/overlay" >> ~/.fluxbox/init
Bước kế tiếp là chỉnh phím tắt cho fluxbox. Cần thêm gói i3lock (hoặc alock?), alsa-utils, mpc, mpd, emacs và libaosd. Và xev để tìm cho đúng mã phím. Không chừng cần xmodmap luôn. Nên cài thêm arandr nếu ngán xrandr.
cat >~/.fluxbox/keys <<\EOF
# click on the desktop to get menus
OnDesktop Mouse1 :HideMenus
OnDesktop Mouse2 :WorkspaceMenu
OnDesktop Mouse3 :RootMenu
# alt + left/right click to move/resize a window
OnWindow Mod1 Mouse1 :MacroCmd {Raise} {Focus} {StartMoving}
OnWindowBorder Move1 :StartMoving
OnWindow Mod1 Mouse2 :MacroCmd {Raise} {Focus} {StartResizing NearestCorner}
OnLeftGrip Move1 :StartResizing bottomleft
OnRightGrip Move1 :StartResizing bottomright
# alt + middle click to lower the window
OnWindow Mod1 Mouse2 :Lower
# control-click a window's titlebar and drag to attach windows
OnTitlebar Control Mouse1 :StartTabbing
# double click on the titlebar to shade
OnTitlebar Double Mouse1 :Maximize
# left click on the titlebar to move the window
OnTitlebar Mouse1 :MacroCmd {Raise} {Focus} {ActivateTab}
OnTitlebar Move1 :StartMoving
# middle click on the titlebar to lower
OnTitlebar Mouse2 :Lower
# right click on the titlebar for a menu of options
OnTitlebar Mouse3 :WindowMenu
# alt-tab
Mod1 Tab :NextWindow {groups} (workspace=[current])
Mod1 Shift Tab :PrevWindow {groups} (workspace=[current])
# cycle through tabs in the current window
Mod4 Tab :NextTab
Mod4 Shift Tab :PrevTab
# go to a specific tab in the current window
Mod4 1 :Tab 1
Mod4 2 :Tab 2
Mod4 3 :Tab 3
Mod4 4 :Tab 4
Mod4 5 :Tab 5
Mod4 6 :Tab 6
Mod4 7 :Tab 7
Mod4 8 :Tab 8
Mod4 9 :Tab 9
Mod1 F1 :Exec urxvt
Mod1 F2 :Exec rofi -show run
Mod1 F3 :Exec emacsclient -c
Mod4 L :Exec ~/opt/i3lock/bin/i3lock -i ~/u/fondo1p.png -C -c 000000; xset dpms force off
Mod4 D :ShowDesktop
Mod4 Up :MacroCmd {ResizeTo 100% 50%} {MoveTo 0 0}
Mod4 Down :MacroCmd {ResizeTo 100% 50%} {MoveTo 0 50%}
Mod4 Left :MacroCmd {ResizeTo 50% 100%} {MoveTo 0 0}
Mod4 Right :MacroCmd {ResizeTo 50% 100%} {MoveTo 50% 0}
Mod4 Prior :Exec amixer sset Master 4%+
Mod4 Next :Exec amixer sset Master 4%-
Mod4 M :Exec amixer sset Master toggle
Mod4 Pause :Exec mpc toggle
# current window commands
Mod1 F4 :Close
Mod1 F5 :Kill
Mod1 F9 :Minimize
Mod1 F10 :Maximize
Mod1 F11 :Fullscreen
# open the window menu
Mod1 space :WindowMenu
# exit fluxbox
Control Mod1 Delete :Exit
# change to previous/next workspace
Control Mod1 Left :PrevWorkspace
Control Mod1 Right :NextWorkspace
# send the current window and follow it to previous/next workspace
Control Mod1 Shift Left :TakeToPrevWorkspace
Control Mod1 Shift Right :TakeToNextWorkspace
# change to a specific workspace
Control F1 :Workspace 1
Control F2 :Workspace 2
Control F3 :Workspace 3
Control F4 :Workspace 4
Control F5 :Workspace 5
Control F6 :Workspace 6
Control F7 :Workspace 7
Control F8 :Workspace 8
Control F9 :Workspace 9
Control F10 :Workspace 10
Control F11 :Workspace 11
Control F12 :Workspace 12
EOF
Phần hai, nhạc nhọt. Cấu hình mpd. Cần pulseaudio
mkdir -p ~/.config/mpd
cat >~/.config/mpd/mpd.conf <<EOF
music_directory "$HOME/music"
playlist_directory "$HOME/.config/mpd/playlists"
db_file "$HOME/.config/mpd/database"
log_file "syslog"
pid_file "$HOME/.config/mpd/pid"
state_file "$HOME/.config/mpd/state"
user "$USER"
bind_to_address "localhost"
bind_to_address "$HOME/.config/mpd/socket"
audio_output {
type "pulse"
name "My Pulse Output"
}
filesystem_charset "UTF-8"
EOF
systemctl --user enable mpd
và last.fm (cần mpdas)
cat >~/.mpdas <<EOF
username = pclouds
password = $(echo -n PASSWORD | md5sum | cut -f -d " ")
EOF
cat >~/.local/share/systemd/user/mpdas.service <<EOF
[Unit]
Description=AudioScrobbler client for MPD
After=mpd.service
[Service]
ExecStart=/usr/bin/mpdas
[Install]
WantedBy=multi-user.target
EOF
systemctl --user enable mpdas
Cài thêm mpc và ncmpc để xài cho tiện.
Chạy emacs daemon tự động:
cat >~/.local/share/systemd/user/emacs.service <<EOF
[Unit]
Description=Emacs: the extensible, self-documenting text editor
[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
Restart=always
[Install]
WantedBy=default.target
EOF
systemctl --user enable emacs
Và màu mè (~/.emacs
thì sao?). Cần terpinus-font.
cat >>~/.Xresources <<EOF
emacs.font: -xos4-terpinus-medium-*-normal-*-14-*-iso10646-1
emacs.reverseVideo: true
Emacs*useXIM: false
EOF
Cấu hình XDG (cần gói xdg-utils), v.d.
xdg-mime default evince.desktop application/pdf
Cấu hình terminal (và tmux)
cat >>~/.Xresources <<EOF
Rxvt*reverseVideo: true
Rxvt*font: -xos4-terpinus-medium-*-normal-*-14-*-iso10646-1
Rxvt*boldFont: -xos4-terpinus-bold-*-normal-*-14-*-iso10646-1
Rxvt*scrollBar: false
Rxvt*termName: rxvt-256color
URxvt*color12: rgb:5c/5c/ff
Rxvt*cursorColor: #ffffff
URxvt*internalBorder: 0
URxvt*externalBorder: 0
URxvt*.cutchars: "()*,;<>[]{}|\"'`#?/?&=."
URxvt.keysym.C-semicolon: urlmatch:hint
EOF
cat >~/.tmux.conf <<EOF
set -g prefix C-a
unbind-key C-b
#bind-key -n C-b send-prefix
bind-key a send-prefix
bind-key C-a select-window -l
bind-key Tab last-pane
bind-key R new-window -n root -t 9 su
bind-key Space next-window
bind-key Escape copy-mode
bind-key C-Space select-pane -t :.+
set -g history-limit 5000
set-option -g pane-base-index 1
set -s escape-time 0
set -g display-panes-time 3000
#set-option base-index 1
#set -g status off
#set -g set-titles on
# set -g utf8 on
# xterm is on reverse video..
set-option -g message-bg black
set-option -g message-fg white
set-option -g status-fg white
set-option -g status-bg black
set-window-option -g window-status-current-bg red
set-window-option -g automatic-rename off
set-window-option -g allow-rename off
EOF
cat >~/.local/bin/S <<\EOF
#!/bin/sh
R="$1"
test -n "$R" || R=def
$HOME/opt/tmux/bin/tmux -u attach-session -t $R ||
$HOME/opt/tmux/bin/tmux -u new-session -t $R
EOF
chmod u+x ~/.local/bin/S
cat >>~/.bashrc <<\EOF
_S() {
if [ "$COMP_CWORD" = 1 ]; then
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=( $(compgen -W "`tmux ls -F '#{session_name}'`" -- "$cur") )
return 0
fi
}
complete -o bashdefault -o default -o nospace -F _S S
EOF
Cấu hình ccache để xài với gcc mới
echo 'keep_comments_cpp = true' >> ~/.ccache/ccache.conf
Cấu hình python repl
echo 'export PYTHONSTARTUP=~/.pythonrc' >>~/.bashrc
cat >~/.pythonrc <<\EOF
import rlcompleter, readline
readline.parse_and_bind('tab: complete')
EOF
Systemd. Tắt systemd-coredump
echo 'kernel.core_pattern = core' >/etc/sysctl.d/50-coredump.conf
và tắt journald
rm -rf /var/log/journal
(còn tiếp?)
Vói openrc thì nên bật /var/log/rc.log trong /etc/rc.conf
rc_logger="YES"
Với gkrellm nhớ chép /usr/share/gkrellm2/themes/Industrial qua.
Với Steam thêm mấy cái này vào /usr/bin/steam
export GTK_IM_MODULE=
export LANG=C
export QT_IM_MODULE=
export XMODIFIERS=
export __GL_SHADER_DISK_CACHE=1
export __GL_THREADED_OPTIMIZATIONS=1
ulimit -c 25600
Xem thêm cấu hình nvidia optimus.
Nếu suspend bằng cách đóng nắp laptop xong mở lại đen thui, nhưng chạy OK nếu là tty trước khi đóng thì xem thêm https://bugs.gentoo.org/287710 và chỉnh elogind lại. Một cái script ngắn như vầy (/lib64/elogind/system-sleep/20-nvidia) có vẻ chạy:
#!/bin/sh
case "${1-}" in
'pre') /usr/bin/nvidia-sleep.sh suspend ;;
'post') /usr/bin/nvidia-sleep.sh resume & ;;
*) exit 1 ;;
esac
(Script hết chạy. Coi https://bugs.gentoo.org/693384 và https://github.com/elogind/elogind/issues/140). Tạm thời dùng
echo mem > /sys/power/state
Với firefox, vào about:config
và chỉnh
widget.windows.overlay-scrollbars.enabled
and
accessibility.typeaheadfind.enablesound
to false.
Cái Nitro AN515-55 bị hư màn hình, từ dưới lên. Xém xíu nữa sắm máy mới cho tới khi tìm thấy bài này (khi đang kiếm máy mới).
Túm lại là giảm refresh rate xuống trong .xinitrc
xrandr -r 60
Và giảm tương tự cho console mode bằng cách thêm vào kernel parameters
video=1920x1080@60m
.
Cập nhật 15 lần. Lần cuối: Tue Jan 02 18:04:51+0001 2024
Fri Jan 4 10:17:39 +07 2019
Antenna Calibration
Bài trước mô tả beam forming dựa trên một ngầm định: tín hiệu gửi ra ở tám ăn-ten cùng lúc (sau đó BF sẽ cố tình làm lệch tín hiệu). Trên thực tế, phần cứng và môi trường ảnh hưởng dẫn đến tám ăn-ten gửi cùng tín hiệu không cùng thời điểm mà lệch chút đỉnh. Cái sự lệch này baseband không "thấy" được và nó làm giảm chất lượng BF.
Để tránh tình huống này, ta cần cân chỉnh mỗi ăn-ten, bảo đảm cùng tín hiệu gửi ra đồng thời ở tất cả ăn-ten (trước khi kích hoạt BF). Phần cân chỉnh thực chất không khó. Phần khó là đo độ trễ của các ăn-ten.
Nguyên tắc đo độ lệch cũng đơn giản. Gửi cái gì đó ra bên ngoài, thu sóng gửi ra, tính toán tính tiếc, ra được độ lệch giữa mỗi ăn ten. Dễ òm!
Nói đúng ra nó chỉ "dễ òm" trong trường hợp lý tưởng: không nhiễu, gửi trên mỗi một tần số (hoặc không có interfere giữa các băng thông với nhau). Trường hợp lý tưởng không bao giờ xảy ra trên thực tế. Chẹp.
Cái đầu tiên. Gửi cái gì ra (và làm sao tìm ra cái mình gửi). Một trong những tín hiệu được dùng là Zadoff-Chu sequence. Tín hiệu được phát sinh dùng Z-C sequence khi nhận vào, chạy cross correlation với tính hiệu gốc, nếu tìm ra thì chỉ có đúng một "peak". Có nghĩa là không có tìm nhầm được. Công thức Z-C được dùng để tính phase và amplitude (dạng số phức) của từng tần số gửi ra. Thông thường ta phải gửi ra trên toàn bộ băng thông (ít ra là phần băng thông được thực sự dùng để gửi tín hiệu trên thực tế). Dùng IFFT để có tín hiệu ở time domain.
OK dùng Z-C sequence để phát sinh tính hiệu cho, ví dụ 1 "symbol" (1 symbol là tín hiệu radio trong một khoảng thời gian nhất định, với LTE là 0.5ms / 7, và chứa "N" bit sau khi giải mã). Tín hiệu được gửi ra đồng thời cho tất cả ăn ten. Tín hiệu được bắt lại ở tất cả ăn ten (thời điểm bắt có thể trước thời điểm gửi chút đỉnh để bảo đảm không bắt sót). Chạy xcorr tìm ra vị trí Z-C sequence ở tất cả các ăn ten. Dựa vào vị trí (đơn vị số mẫu IQ), ta có thể thấy độ lệch của các ăn ten...
Nếu độ lệch giữa các ăn ten lớn hơn độ dài (thời gian) của một mẫu IQ. Cái này phụ thuộc vào tốc độ lấy mẫu. Nếu tốc độ thấp, mỗi mẫu IQ chiếm nhiều thời gian hơn. Nếu độ lệch thực sự nhỏ hơn một mẫu IQ thì mần sao tìm ra?
Mần DSP ít ai chơi time domain. Để xác định độ lệch nhỏ thế này, có thể chuyển qua frequency domain và đo độ lệch pha. Một khi đã xác định điểm bắt đầu của Z-C sequence (trong time domain), có thể dùng FFT để chuyển qua frequency domain. Dễ òm.
(Ghi chú, dùng xcorr chỉ là một trong hai (hay nhiều hơn?) cách để xác định vị trí bắt đầu của tín hiệu trong time domain. Cách thứ hai là dùng Cyclic Prefix. Cách này có thể tính vị trí chỉ cần tín hiệu nhận, không cần tín hiệu gửi. Nhưng sẽ phải gửi nhiều hơn một Z-C sequence để tăng độ chính xác. LTE dùng cách này để tính vị trí bắt đầu của tín hiệu).
OK chuyển qua frequency domain thì tính độ lệch (pha) không còn đơn giản như trong time domain (chỉ cần đếm số mẫu IQ). Nhưng cũng không phức tạp lắm (hoặc từ từ mới phức tạp). Ví dụ với một tần số cụ thể, tín hiệu gốc là:
ae^{bi}
với a là phần thực (và là amplitude, b là pha) và tín hiệu nhận được là
Ae^{Bi}
thì có thể tính ra phần trễ (và độ tăng giảm amplitude luôn nhưng cái đó kém quan trọng hơn):
ae^{bi} * ce^{di} = Ae^{Bi}
d = B - b
c = A / a
d
là độ lệch pha (theo radian) cho tần số này. Làm y chang cho tất
cả các tần số.
Trên thực tế, ta có thể gửi và nhận nhiều Z-C sequence (vd, mỗi symbol một sequence), và điều phải tính độ lệch cho tất cả các sequence (trên tất cả tần số). Nếu tính toán bằng số phức thì "impairment transfer function" chỉ đơn giản là
sum(RX(x)/TX(x)) # for each sequence x
bởi vì khi cộng số phức thì pha gần như không đổi. Pha tổng cộng sẽ là giá trị trung bình của độ lệch pha của tất cả sequence (đúng không ta?). Chuyển đổi sang pha/amplitude sau khi tính toán bằng số phức sẽ đơn giản hơn nhiều.
(Ghi chú, bởi vì mẫu I/Q dạng số phức không phải thực sự là amplitude và pha, cần phải chuyển đổi lại. Xem thêm chỗ này)
OK. Giả định gửi và nhận một Z-C sequence equation/block ra ngoài trên năm tần số ("frequency bin") khác nhau. Sau khi tính toán xong, ta có năm độ lệch pha (nói cách khác, năm độ lệch về thời gian). Nhưng mà ở time domain, lệch năm cái làm sao xử lý? Năm tần số chuyển qua time domain chỉ còn là một, và phải chỉ có một độ lệch (bất kể là thời gian hay pha).
... còn tiếp ...
Fri Jan 4 09:53:01 +07 2019
Beam forming
Beam forming (BF) là cách tăng năng lượng sóng vô tuyến cho một thiết bị nhận (UE) nhất định. Tại sao cần BF? Dĩ nhiên là tăng chất lượng sóng thì khách hàng ít càm ràm hơn. Nhưng với 5G thì BF là bắt buộc bởi vì khi gửi tần số cao (mmWave) thì "gain" ở phía UE giảm và không có nhiều cách để tăng chất lượng sóng lên.
Túm lại là vậy. BF hoạt động bằng cách "chỉa" nhiều ăn-ten vào 1 UE để tăng năng lượng sóng lên (cho mỗi UE đó). Bởi vì dùng nhiều ăn-ten, BF thường cần ăn-ten array, một trạm phát có thể có 64-256 ăn-ten.
Chôm cái hình từ đây
Như hình vẽ, ta có tám ăn-ten xếp thành một hàng và cái đầu nhận nằm lệch về phía bên phải. Bởi vì sóng phát ra ở mọi hướng, UE sẽ nhận được tín hiệu từ cả tám ăn-ten. Tuy nhiên bởi vì khoảng cách từ tám ăn-ten đến UE khác nhau (dù rất nhỏ), tín hiệu ở thời điểm nhận không giống nhau (dòm ở đường p1-p8).
Nếu tính hiệu lệch chút đỉnh vậy mà tổng hợp lại thành một thì nó nhiều khả năng làm suy giảm tín hiệu, hoặc tệ hơn là biến đổi tín hiệu. Nếu làm sao để UE nhận tám tín hiệu y như nhau, tám tín hiệu chứa cùng thông tin, tổng hợp tám luồng lại, năng lượng nhận nhân tám!
Nhưng mà làm sao? Dễ òm. Thay vì gửi cùng tín hiệu ở tám ăn-ten cùng thời điểm, ta gửi lệch chút đỉnh để bù đắp cho độ lệch về khoảng cách (đến UE) của tám ăn-ten. Cái ăn-ten gần UE nhất phải gửi trễ nhất, cái xa nhất gửi ngay tức thì. Nếu canh đúng, tám tín hiệu sẽ đến cùng thời điểm.
Điểm duy nhất còn lại cần nói thêm là độ lệch pha và độ lệch thời gian/khoảng cách là như nhau. Độ lệch (về thời gian hoặc khoảng cách) giữa những ăn-ten rất rất nhỏ. Tinh chỉ độ lệch giữa các ăn-ten bằng cách điều chỉnh pha (ở baseband, trong frequency domain) dễ hơn và chính xác hơn so với chỉnh lệch thời gian (time domain). Nhiều khi độ lệch trong time domain là "0.5 sample", coi như không chỉnh được cho đến khi chuyển tính hiệu thành analog.