Chapter 11

FiRa 세션: 라운드·슬롯·역할

6장의 핑퐁은 두 기기가 “언제, 어느 채널에서, 어떤 코드로, 누가 먼저” 보낼지 이미 안다고 가정했다. 실제로는 그 약속부터 정해야 한다. iPhone과 갤럭시가 서로를, 또 다른 회사의 태그를 잴 수 있으려면 약속의 형식이 같아야 한다. FiRa Consortium이 정하고 Android UWB 스택이 구현한 그 약속, 세션을 들여다본다.

두 쌍의 역할

휴대폰과 분실물 태그라면 휴대폰이 컨트롤러·시작자, 태그가 컨트롤리·응답자다. Android는 TDoA용으로 광고자·관찰자 역할도 둔다(9장).

역할 값: Android FiraParams.java의 RANGING_DEVICE_ROLE_RESPONDER = 0, _INITIATOR = 1, _ADVERTISER = 5, _OBSERVER = 6 · 일대다: MULTI_NODE_MODE_UNICAST = 0, _ONE_TO_MANY = 1, _MANY_TO_MANY = 2

RSTU, 슬롯, 라운드, 간격

FiRa의 시간은 네 층이다.

  1. RSTU(Ranging Scheduling Time Unit): 1/1.2 µs ≈ 833.3 ns. 499.2 MHz 칩 416개 길이다. 자동차 키(CCC)는 400 RSTU = 1/3 ms를 “chap”이라 부른다.
  2. 슬롯: 프레임 하나를 보내는 칸. Android 기본 2,400 RSTU = 2 ms. 4장의 거리 측정 프레임(약 140 µs)이 넉넉히 들어간다.
  3. 라운드: 한 번의 거리 측정에 필요한 메시지들이 차례로 들어가는 슬롯 묶음. 기본 25슬롯 = 50 ms.
  4. 측정 간격(ranging interval): 라운드가 다시 돌아오는 주기. 기본 200 ms, 즉 초당 5번. 라운드 사이에는 칩이 잔다(12장).

기본값: Android external/uwb fira_app_config_params.rs의 DEFAULT_SLOT_DURATION_RSTU = 2400, DEFAULT_RANGING_DURATION_MS = 200 · FiraParams.java의 SLOTS_PER_RR = 25 · 1 chap = 400 RSTU: aliro_app_config_params.rs의 CHAP_IN_RSTU · RSTU 길이 1/1.2 µs는 chap = 1/3 ms와 400 RSTU의 관계에서 나온 값(= 416 칩 ÷ 499.2 MHz)

회의 발언 순서표

여러 사람이 한 마이크를 쓰는 회의에서는 순서표를 미리 나눠 준다. “1번 자리는 사회자, 2~5번은 각 팀, 마지막은 정리”. 각자 자기 차례에만 말하니 부딪히지 않는다. FiRa의 라운드가 순서표, 슬롯이 발언 칸이다. 사람이 많아지면 순서표가 길어지고, 회의(측정) 간격도 길어진다.

예측해 보기

DS-TWR 일대다, 라운드가 25슬롯이다. 응답자는 최대 몇 개까지 넣을 수 있을까?

DS-TWR 일대다에 필요한 슬롯 = 4 + 2 × 응답자 수.

4 + 2n ≤ 25에서 n = 10. 단방향(SS)이면 3 + n이라 22개까지 들어간다. 정확도와 응답자 수를 맞바꾸는 셈이다. 아래 시간표에서 응답자 수를 늘려 보자.
SIMULATOR

라운드 시간표 만들기

측정 방식
라운드에 필요한 슬롯—
라운드 길이 / 간격—
이 설정의 최대 응답자—
위: 라운드 하나의 슬롯(색 = 메시지 종류, 회색 = 빈 슬롯). 아래: 측정 간격 안에서 라운드가 차지하는 부분. 해볼 것: ① 기본값(2 ms, 25슬롯, 200 ms)에 응답자 4대면 슬롯이 남는다. ② 응답자를 늘리면 라운드에 필요한 슬롯이 늘어 25를 넘으면 Android가 “슬롯 부족” 오류로 세션을 멈춘다. ③ 슬롯을 1 ms로 줄이면 같은 라운드 시간에 두 배를 담는다. 메시지 수(단순화): SS = 제어 1 + Poll 1 + 응답 N + 결과 보고 1, DS(결과 따로) = 제어 1 + Poll 1 + 응답 N + Final 1 + 측정 보고 1 + 결과 N. 실제 FiRa 메시지 구성은 설정에 따라 조금 다르다.

슬롯 부족·간격 오류: uci_packets.pdl의 ERROR_INSUFFICIENT_SLOTS_PER_RR = 0x21, ERROR_INVALID_RANGING_DURATION = 0x23 · 측정 방식 이름: RANGING_ROUND_USAGE_SS_TWR_DEFERRED_MODE, _DS_TWR_DEFERRED_MODE, _NON_DEFERRED_MODE

앱에서 칩까지: 세션이 열리는 순서

앱은 UWB 칩을 직접 다루지 않는다. Android에서는 앱 → UWB 시스템 서비스 → UWB 칩(UWBS) 순으로 내려가고, 서비스와 칩은 UCI(UWB Command Interface)라는 명령 형식으로 이야기한다. 그 전에 두 기기는 UWB 밖의 통로(대개 BLE, 12장)로 상대의 주소와 세션 설정, 보안 키를 주고받는다. 이것을 대역 외(OOB) 설정이라 한다.

INTERACTIVE

세션 하나의 일생

명령 이름은 Android external/uwb의 uci_packets.pdl에 정의된 이름이다(SESSION_INIT, SESSION_SET_APP_CONFIG, SESSION_START(RANGE_START), SESSION_STOP, SESSION_DEINIT). 앱 쪽 이름(RangingSession 등)은 Android 버전마다 조금 다르다.

세션끼리 부딪히지 않게: 라운드 도약

같은 방에서 여러 휴대폰이 각자 세션을 돌리면, 같은 채널·같은 간격인 두 세션의 라운드가 겹칠 수 있다. 시계가 거의 같은 속도로 가므로, 한 번 겹치면 계속 겹친다. 그래서 FiRa는 간격 몇 개를 블록으로 묶고, 블록마다 라운드를 놓는 자리를 무작위로 바꾼다(라운드 도약, hopping). 겹쳐도 다음 블록에서는 대개 비켜 간다.

SIMULATOR

두 세션의 충돌

충돌한 블록—
기대 충돌률—
연속 충돌 최대—
위아래 줄 = 세션 A·B, 칸 = 블록 안의 라운드 자리, 색칠 = 그 블록에서 라운드를 놓은 자리, 빨강 = 둘이 겹친 블록. 도약을 끄면 처음 위치가 그대로 이어져, 겹치면 매번 겹친다. 도약을 켜면 블록마다 1 ÷ 자리 수 확률로만 겹친다. 모델: 두 세션의 블록 경계가 맞고 자리를 독립적으로 고른다고 가정.

도약·블록 설정: uci_packets.pdl의 HOPPING_MODE = 0x2C, BLOCK_STRIDE_LENGTH = 0x2D · CCC 디지털 키의 도약 방식: CccParams.java의 HOPPING_CONFIG_MODE_CONTINUOUS·_ADAPTIVE, HOPPING_SEQUENCE_AES

핵심 정리

  1. 컨트롤러·컨트롤리 = 누가 설정·시간표를 정하나, 시작자·응답자 = 누가 Poll을 보내나.
  2. RSTU ≈ 833 ns(1 chap = 400 RSTU = 1/3 ms). Android 기본: 슬롯 2,400 RSTU(2 ms), 라운드 25슬롯(50 ms), 간격 200 ms(초당 5번).
  3. 일대다에서 응답자가 늘면 라운드에 필요한 슬롯이 늘고, 넘치면 “슬롯 부족”으로 멈춘다.
  4. 앱 → UWB 서비스 → UCI(SESSION_INIT → SET_APP_CONFIG → START) → 칩. 그 전에 BLE 등으로 OOB 설정.
  5. 라운드 도약은 블록마다 라운드 자리를 바꿔, 세션끼리 계속 부딪히는 것을 막는다.

확인 퀴즈

Android 기본 슬롯 2,400 RSTU는 몇 ms인가?

2,400 × 1/1.2 µs = 2,000 µs.

측정 간격 200 ms면 초당 측정은?

1,000 ÷ 200 = 5.

라운드 도약이 막는 것은?

블록마다 자리를 바꿔 겹침을 확률적으로 만든다.

Android UWB 서비스가 칩에 세션 설정 값을 넣는 UCI 명령은?

SESSION_INIT으로 세션을 만들고 SET_APP_CONFIG로 채널·슬롯·간격 등을 넣은 뒤 SESSION_START.