Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions py/pica/pica/packets/uci.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,21 +882,6 @@ def from_int(v: int) -> Union[int, 'CapTlvType']:
return v


class AoaResultReqType(enum.IntEnum):
AOA_DISABLE = 0x0
AOA_ENABLE = 0x1
AOA_ENABLE_AZIMUTH = 0x2
AOA_ENABLE_ELEVATION = 0x3
AOA_ENABLE_INTERLEAVED = 0xf0

@staticmethod
def from_int(v: int) -> Union[int, 'AoaResultReqType']:
try:
return AoaResultReqType(v)
except ValueError as exn:
raise exn


class DeviceState(enum.IntEnum):
DEVICE_STATE_READY = 0x1
DEVICE_STATE_ACTIVE = 0x2
Expand Down
58 changes: 48 additions & 10 deletions src/app_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ const DEFAULT_DL_TDOA_ANCHOR_CFO: uci::DlTdoaAnchorCfo = uci::DlTdoaAnchorCfo::A
const DEFAULT_DL_TDOA_TX_ACTIVE_RANGING_ROUNDS: bool = false;
const DEFAULT_DL_TDOA_TIME_REFERENCE_ANCHOR: bool = false;
const DEFAULT_DL_TDOA_RESPONDER_TOF: bool = false;
const DEFAULT_AOA_RESULT_REQ: uci::AoaResultReq = uci::AoaResultReq::AoaEnabled;
const DEFAULT_AOA_BOUND_CONFIG: [u8; 8] = [0x00, 0xa6, 0x00, 0x5a, 0x00, 0xd3, 0x00, 0x2d];

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand All @@ -138,9 +139,20 @@ struct AoaBounds {
}

impl AoaBounds {
fn contains(&self, azimuth: i16, elevation: i16) -> bool {
(self.min_azimuth..=self.max_azimuth).contains(&azimuth)
&& (self.min_elevation..=self.max_elevation).contains(&elevation)
fn contains(&self, azimuth: i16, elevation: i16, req: uci::AoaResultReq) -> bool {
match req {
uci::AoaResultReq::AoaDisabled => false,
uci::AoaResultReq::AoaEnabled => {
(self.min_azimuth..=self.max_azimuth).contains(&azimuth)
&& (self.min_elevation..=self.max_elevation).contains(&elevation)
}
uci::AoaResultReq::AoaEnabledAzimuthOnly => {
(self.min_azimuth..=self.max_azimuth).contains(&azimuth)
}
uci::AoaResultReq::AoaEnabledElevationOnly => {
(self.min_elevation..=self.max_elevation).contains(&elevation)
}
}
}
}
const DEFAULT_CCC_TLVS: [(uci::AppConfigTlvType, Bytes); 5] = [
Expand Down Expand Up @@ -258,7 +270,7 @@ impl AppConfig {
),
(
uci::AppConfigTlvType::AoaResultReq,
Bytes::from_static(&[uci::AoaResultReq::AoaEnabled as u8]),
Bytes::from_static(&[DEFAULT_AOA_RESULT_REQ as u8]),
),
(
uci::AppConfigTlvType::RframeConfig,
Expand Down Expand Up @@ -733,6 +745,11 @@ impl AppConfig {
.unwrap_or(DEFAULT_SUSPEND_RANGING_ROUNDS)
}

pub fn aoa_result_req(&self) -> uci::AoaResultReq {
self.get_enum(uci::AppConfigTlvType::AoaResultReq)
.unwrap_or(DEFAULT_AOA_RESULT_REQ)
}

pub fn set_number_of_controlees(&mut self, value: u8) {
self.tlvs.insert(
uci::AppConfigTlvType::NumberOfControlees,
Expand Down Expand Up @@ -779,9 +796,27 @@ impl AppConfig {
.unwrap_or(DEFAULT_SLOTS_PER_RR)
}

pub fn session_info_ntf_config(&self) -> uci::SessionInfoNtfConfig {
self.get_enum(uci::AppConfigTlvType::SessionInfoNtfConfig)
.unwrap_or(DEFAULT_SESSION_INFO_NTF_CONFIG)
pub fn effective_session_info_ntf_config(&self) -> uci::SessionInfoNtfConfig {
let config = self
.get_enum(uci::AppConfigTlvType::SessionInfoNtfConfig)
.unwrap_or(DEFAULT_SESSION_INFO_NTF_CONFIG);
if self.aoa_result_req() == uci::AoaResultReq::AoaDisabled {
match config {
uci::SessionInfoNtfConfig::EnableAoaTrigger
| uci::SessionInfoNtfConfig::EnableAoaEdgeTrigger => {
uci::SessionInfoNtfConfig::Disable
}
uci::SessionInfoNtfConfig::EnableProximityAoaTrigger => {
uci::SessionInfoNtfConfig::EnableProximityTrigger
}
uci::SessionInfoNtfConfig::EnableProximityAoaEdgeTrigger => {
uci::SessionInfoNtfConfig::EnableProximityEdgeTrigger
}
_ => config,
}
} else {
config
}
}

pub fn in_band_termination_attempt_count(&self) -> u8 {
Expand Down Expand Up @@ -925,8 +960,10 @@ impl AppConfig {
pub fn is_within_bounds(&self, distance: u16, azimuth: i16, elevation: i16) -> bool {
let within_proximity =
(self.near_proximity_config()..=self.far_proximity_config()).contains(&distance);
let within_aoa = self.aoa_bound_config().contains(azimuth, elevation);
match self.session_info_ntf_config() {
let within_aoa =
self.aoa_bound_config()
.contains(azimuth, elevation, self.aoa_result_req());
match self.effective_session_info_ntf_config() {
uci::SessionInfoNtfConfig::EnableProximityTrigger
| uci::SessionInfoNtfConfig::EnableProximityEdgeTrigger => within_proximity,
uci::SessionInfoNtfConfig::EnableAoaTrigger
Expand All @@ -935,7 +972,8 @@ impl AppConfig {
| uci::SessionInfoNtfConfig::EnableProximityAoaEdgeTrigger => {
within_proximity && within_aoa
}
uci::SessionInfoNtfConfig::Enable | uci::SessionInfoNtfConfig::Disable => true,
uci::SessionInfoNtfConfig::Enable => true,
uci::SessionInfoNtfConfig::Disable => false,
}
}

Expand Down
133 changes: 83 additions & 50 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,17 @@ const fn degrees_to_q9_7(deg: i16) -> i16 {
deg.saturating_mul(128)
}

fn encode_aoa(measurement: RangingMeasurement, req: uci::AoaResultReq) -> (u16, u8, u16, u8) {
let azimuth = degrees_to_q9_7(measurement.azimuth) as u16;
let elevation = degrees_to_q9_7(i16::from(measurement.elevation)) as u16;
match req {
uci::AoaResultReq::AoaDisabled => (0, 0, 0, 0),
uci::AoaResultReq::AoaEnabled => (azimuth, 100, elevation, 100),
uci::AoaResultReq::AoaEnabledAzimuthOnly => (azimuth, 100, 0, 0),
uci::AoaResultReq::AoaEnabledElevationOnly => (0, 0, elevation, 100),
}
}

#[derive(Debug)]
enum TwoWayRangingMeasurement {
Short(ShortAddressTwoWayRangingMeasurement),
Expand All @@ -155,25 +166,34 @@ enum TwoWayRangingMeasurement {

impl TwoWayRangingMeasurement {
fn new(
app_config: &AppConfig,
mac_address: &MacAddress,
local: RangingMeasurement,
remote: RangingMeasurement,
) -> Self {
let (aoa_azimuth, aoa_azimuth_fom, aoa_elevation, aoa_elevation_fom) =
encode_aoa(local, app_config.aoa_result_req());
let (
aoa_destination_azimuth,
aoa_destination_azimuth_fom,
aoa_destination_elevation,
aoa_destination_elevation_fom,
) = encode_aoa(remote, uci::AoaResultReq::AoaEnabled);
match mac_address {
MacAddress::Short(address) => {
Self::Short(ShortAddressTwoWayRangingMeasurement {
mac_address: u16::from_le_bytes(*address),
status: uci::Status::Ok,
nlos: 0, // in Line Of Sight
distance: local.range,
aoa_azimuth: degrees_to_q9_7(local.azimuth) as u16,
aoa_azimuth_fom: 100, // Yup, pretty sure about this
aoa_elevation: degrees_to_q9_7(i16::from(local.elevation)) as u16,
aoa_elevation_fom: 100, // Yup, pretty sure about this
aoa_destination_azimuth: degrees_to_q9_7(remote.azimuth) as u16,
aoa_destination_azimuth_fom: 100,
aoa_destination_elevation: degrees_to_q9_7(i16::from(remote.elevation)) as u16,
aoa_destination_elevation_fom: 100,
aoa_azimuth,
aoa_azimuth_fom,
aoa_elevation,
aoa_elevation_fom,
aoa_destination_azimuth,
aoa_destination_azimuth_fom,
aoa_destination_elevation,
aoa_destination_elevation_fom,
slot_index: 0,
rssi: u8::MAX,
})
Expand All @@ -184,14 +204,14 @@ impl TwoWayRangingMeasurement {
status: uci::Status::Ok,
nlos: 0,
distance: local.range,
aoa_azimuth: degrees_to_q9_7(local.azimuth) as u16,
aoa_azimuth_fom: 100,
aoa_elevation: degrees_to_q9_7(i16::from(local.elevation)) as u16,
aoa_elevation_fom: 100,
aoa_destination_azimuth: degrees_to_q9_7(remote.azimuth) as u16,
aoa_destination_azimuth_fom: 100,
aoa_destination_elevation: degrees_to_q9_7(i16::from(remote.elevation)) as u16,
aoa_destination_elevation_fom: 100,
aoa_azimuth,
aoa_azimuth_fom,
aoa_elevation,
aoa_elevation_fom,
aoa_destination_azimuth,
aoa_destination_azimuth_fom,
aoa_destination_elevation,
aoa_destination_elevation_fom,
slot_index: 0,
rssi: u8::MAX,
})
Expand Down Expand Up @@ -347,13 +367,16 @@ impl DlTdoaMeasurement {
}

fn new(
app_config: &AppConfig,
anchor: &device::DlTdoaAnchor,
local: RangingMeasurement,
message_type: uci::DlTdoaMessageType,
block_index: u16,
tx_timestamp_length: uci::DlTdoaTimestampLength,
tx_timestamp: u64,
) -> Self {
let (aoa_azimuth, aoa_azimuth_fom, aoa_elevation, aoa_elevation_fom) =
encode_aoa(local, app_config.aoa_result_req());
let rx_timestamp = tx_timestamp.wrapping_add(cm_to_tof_ticks(local.range));
let is_final = message_type == uci::DlTdoaMessageType::FinalDtm;
let (wgs84_location, relative_location) = if is_final {
Expand Down Expand Up @@ -386,10 +409,10 @@ impl DlTdoaMeasurement {
block_index,
round_index: anchor.round_index,
nlos: 0,
aoa_azimuth: degrees_to_q9_7(local.azimuth) as u16,
aoa_azimuth_fom: 100,
aoa_elevation: degrees_to_q9_7(i16::from(local.elevation)) as u16,
aoa_elevation_fom: 100,
aoa_azimuth,
aoa_azimuth_fom,
aoa_elevation,
aoa_elevation_fom,
rssi: u8::MAX,
tx_timestamp_40,
tx_timestamp_64,
Expand Down Expand Up @@ -737,6 +760,7 @@ impl Pica {
.then(|| (active_responders.len() as u64 + 1) * slot_ticks);

let poll_dtm = DlTdoaMeasurement::new(
&session.app_config,
init_anchor,
init_local,
uci::DlTdoaMessageType::PollDtm,
Expand All @@ -759,6 +783,7 @@ impl Pica {
let slot_offset_ticks = slot_idx * slot_ticks;
Some(
DlTdoaMeasurement::new(
&session.app_config,
resp_anchor,
local,
uci::DlTdoaMessageType::ResponseDtm,
Expand All @@ -781,6 +806,7 @@ impl Pica {
.filter(|_| !response_dtms.is_empty())
.map(|final_offset| {
DlTdoaMeasurement::new(
&session.app_config,
init_anchor,
init_local,
uci::DlTdoaMessageType::FinalDtm,
Expand Down Expand Up @@ -809,7 +835,8 @@ impl Pica {
return;
};
let send_ntf = session.app_config.dl_tdoa_role() == Some(uci::DeviceRole::DtTag)
&& session.app_config.session_info_ntf_config() != uci::SessionInfoNtfConfig::Disable;
&& session.app_config.effective_session_info_ntf_config()
!= uci::SessionInfoNtfConfig::Disable;
let ntf_packet = if send_ntf {
let measurements = self.dl_tdoa_measurements(device_handle, session_id, session);
session.encode_dl_tdoa_session_info_ntf(measurements)
Expand Down Expand Up @@ -904,7 +931,12 @@ impl Pica {
let remote = self
.ranging_estimator
.estimate(&peer_handle, &device.handle)?;
Some(TwoWayRangingMeasurement::new(&mac_address, local, remote))
Some(TwoWayRangingMeasurement::new(
&session.app_config,
&mac_address,
local,
remote,
))
})
.unwrap_or_else(|| TwoWayRangingMeasurement::timeout(&mac_address));
measurements.push(measurement);
Expand Down Expand Up @@ -1004,34 +1036,35 @@ impl Pica {
}

let effects = if session.session_type() != SessionType::FiraDataTransferSession {
let (send_ntf, measurements) = match session.app_config.session_info_ntf_config() {
uci::SessionInfoNtfConfig::Disable => (false, Vec::new()),
uci::SessionInfoNtfConfig::Enable => (true, measurements),
uci::SessionInfoNtfConfig::EnableProximityTrigger
| uci::SessionInfoNtfConfig::EnableAoaTrigger
| uci::SessionInfoNtfConfig::EnableProximityAoaTrigger => {
let filtered: Vec<_> = measurements
.into_iter()
.filter(|m| m.is_within_bounds(&session.app_config))
.collect();
(!filtered.is_empty(), filtered)
}
uci::SessionInfoNtfConfig::EnableProximityEdgeTrigger
| uci::SessionInfoNtfConfig::EnableAoaEdgeTrigger
| uci::SessionInfoNtfConfig::EnableProximityAoaEdgeTrigger => {
let emitted: Vec<_> = measurements
.into_iter()
.filter(|m| {
if m.is_within_bounds(&session.app_config) {
session.in_range_peers.insert(m.mac_address())
} else {
session.in_range_peers.remove(&m.mac_address())
}
})
.collect();
(!emitted.is_empty(), emitted)
}
};
let (send_ntf, measurements) =
match session.app_config.effective_session_info_ntf_config() {
uci::SessionInfoNtfConfig::Disable => (false, Vec::new()),
uci::SessionInfoNtfConfig::Enable => (true, measurements),
uci::SessionInfoNtfConfig::EnableProximityTrigger
| uci::SessionInfoNtfConfig::EnableAoaTrigger
| uci::SessionInfoNtfConfig::EnableProximityAoaTrigger => {
let filtered: Vec<_> = measurements
.into_iter()
.filter(|m| m.is_within_bounds(&session.app_config))
.collect();
(!filtered.is_empty(), filtered)
}
uci::SessionInfoNtfConfig::EnableProximityEdgeTrigger
| uci::SessionInfoNtfConfig::EnableAoaEdgeTrigger
| uci::SessionInfoNtfConfig::EnableProximityAoaEdgeTrigger => {
let emitted: Vec<_> = measurements
.into_iter()
.filter(|m| {
if m.is_within_bounds(&session.app_config) {
session.in_range_peers.insert(m.mac_address())
} else {
session.in_range_peers.remove(&m.mac_address())
}
})
.collect();
(!emitted.is_empty(), emitted)
}
};

if send_ntf {
let ntf_packet = match session.app_config.mac_address_mode() {
Expand Down
11 changes: 0 additions & 11 deletions src/uci_packets.pdl
Original file line number Diff line number Diff line change
Expand Up @@ -524,17 +524,6 @@ enum CapTlvType : 8 {
},
}


// AOA result request type.
// Values set for AOA_RESULT_REQ config ID.
enum AoaResultReqType : 8 {
AOA_DISABLE = 0x0,
AOA_ENABLE = 0x01,
AOA_ENABLE_AZIMUTH = 0x02,
AOA_ENABLE_ELEVATION = 0x03,
AOA_ENABLE_INTERLEAVED = 0xF0,
}

enum DeviceState : 8 {
DEVICE_STATE_READY = 0x01,
DEVICE_STATE_ACTIVE = 0x02,
Expand Down
Loading
Loading