use serde::Deserialize;
use std::fmt::Debug;
use crate::messages::primitive_aliases::{Code1, Code2, Integer1, Integer2, ScaledSInteger2};
use crate::messages::volume_coverage_pattern::definitions::{ChannelConfiguration, WaveformType};
#[cfg(feature = "uom")]
use uom::si::{
angle::degree,
angular_velocity::degree_per_second,
f64::{Angle, AngularVelocity},
};
#[derive(Clone, PartialEq, Deserialize)]
pub struct ElevationDataBlock {
pub elevation_angle: Code2,
pub channel_configuration: Code1,
pub waveform_type: Code1,
pub super_resolution_control: Code1,
pub surveillance_prf_number: Integer1,
pub surveillance_prf_pulse_count_radial: Integer2,
pub azimuth_rate: Code2,
pub reflectivity_threshold: ScaledSInteger2,
pub velocity_threshold: ScaledSInteger2,
pub spectrum_width_threshold: ScaledSInteger2,
pub differential_reflectivity_threshold: ScaledSInteger2,
pub differential_phase_threshold: ScaledSInteger2,
pub correlation_coefficient_threshold: ScaledSInteger2,
pub sector_1_edge_angle: Code2,
pub sector_1_doppler_prf_number: Integer2,
pub sector_1_doppler_prf_pulse_count_radial: Integer2,
pub supplemental_data: Code2,
pub sector_2_edge_angle: Code2,
pub sector_2_doppler_prf_number: Integer2,
pub sector_2_doppler_prf_pulse_count_radial: Integer2,
pub ebc_angle: Code2,
pub sector_3_edge_angle: Code2,
pub sector_3_doppler_prf_number: Integer2,
pub sector_3_doppler_prf_pulse_count_radial: Integer2,
pub reserved: Integer2,
}
fn decode_angle(raw: Code2) -> f64 {
let mut angle: f64 = 0.0;
for i in 3..16 {
if ((raw >> i) & 1) == 1 {
angle += 180.0 * f64::powf(2.0, (i - 15) as f64);
}
}
return angle;
}
fn decode_angular_velocity(raw: Code2) -> f64 {
let mut angular_velocity: f64 = 0.0;
for i in 3..15 {
if ((raw >> i) & 1) == 1 {
angular_velocity += 22.5 * f64::powf(2.0, (i - 14) as f64);
}
}
if ((raw >> 15) & 1) == 1 {
angular_velocity = -angular_velocity
}
return angular_velocity;
}
impl ElevationDataBlock {
#[cfg(feature = "uom")]
pub fn elevation_angle(&self) -> Angle {
Angle::new::<degree>(decode_angle(self.elevation_angle))
}
pub fn elevation_angle_degrees(&self) -> f64 {
decode_angle(self.elevation_angle)
}
pub fn channel_configuration(&self) -> ChannelConfiguration {
match self.channel_configuration {
0 => ChannelConfiguration::ConstantPhase,
1 => ChannelConfiguration::RandomPhase,
2 => ChannelConfiguration::SZ2Phase,
_ => ChannelConfiguration::UnknownPhase,
}
}
pub fn waveform_type(&self) -> WaveformType {
match self.waveform_type {
1 => WaveformType::CS,
2 => WaveformType::CDW,
3 => WaveformType::CDWO,
4 => WaveformType::B,
5 => WaveformType::SPP,
_ => WaveformType::Unknown,
}
}
pub fn super_resolution_control_half_degree_azimuth(&self) -> bool {
(self.super_resolution_control & 0x1) == 1
}
pub fn super_resolution_control_quarter_km_reflectivity(&self) -> bool {
((self.super_resolution_control >> 1) & 0x1) == 1
}
pub fn super_resolution_control_doppler_to_300km(&self) -> bool {
((self.super_resolution_control >> 2) & 0x1) == 1
}
pub fn super_resolution_control_dual_polarization_to_300km(&self) -> bool {
((self.super_resolution_control >> 3) & 0x1) == 1
}
#[cfg(feature = "uom")]
pub fn azimuth_rate(&self) -> AngularVelocity {
AngularVelocity::new::<degree_per_second>(decode_angular_velocity(self.azimuth_rate))
}
pub fn azimuth_rate_degrees_per_second(&self) -> f64 {
decode_angular_velocity(self.azimuth_rate)
}
pub fn reflectivity_threshold(&self) -> f64 {
self.reflectivity_threshold as f64 * 0.125
}
pub fn velocity_threshold(&self) -> f64 {
self.velocity_threshold as f64 * 0.125
}
pub fn spectrum_width_threshold(&self) -> f64 {
self.spectrum_width_threshold as f64 * 0.125
}
pub fn differential_reflectivity_threshold(&self) -> f64 {
self.differential_reflectivity_threshold as f64 * 0.125
}
pub fn differential_phase_threshold(&self) -> f64 {
self.differential_phase_threshold as f64 * 0.125
}
pub fn correlation_coefficient_threshold(&self) -> f64 {
self.correlation_coefficient_threshold as f64 * 0.125
}
#[cfg(feature = "uom")]
pub fn sector_1_edge_angle(&self) -> Angle {
Angle::new::<degree>(decode_angle(self.sector_1_edge_angle))
}
pub fn sector_1_edge_angle_degrees(&self) -> f64 {
decode_angle(self.sector_1_edge_angle)
}
#[cfg(feature = "uom")]
pub fn sector_2_edge_angle(&self) -> Angle {
Angle::new::<degree>(decode_angle(self.sector_2_edge_angle))
}
pub fn sector_2_edge_angle_degrees(&self) -> f64 {
decode_angle(self.sector_2_edge_angle)
}
#[cfg(feature = "uom")]
pub fn sector_3_edge_angle(&self) -> Angle {
Angle::new::<degree>(decode_angle(self.sector_3_edge_angle))
}
pub fn sector_3_edge_angle_degrees(&self) -> f64 {
decode_angle(self.sector_3_edge_angle)
}
#[cfg(feature = "uom")]
pub fn ebc_angle(&self) -> Angle {
Angle::new::<degree>(decode_angle(self.ebc_angle))
}
pub fn ebc_angle_degrees(&self) -> f64 {
decode_angle(self.ebc_angle)
}
pub fn supplemental_data_sails_cut(&self) -> bool {
(self.supplemental_data & 0x0001) == 1
}
pub fn supplemental_data_sails_sequence_number(&self) -> u8 {
((self.supplemental_data & 0x000E) >> 1) as u8
}
pub fn supplemental_data_mrle_cut(&self) -> bool {
((self.supplemental_data & 0x0010) >> 4) == 1
}
pub fn supplemental_data_mrle_sequence_number(&self) -> u8 {
((self.supplemental_data & 0x00E0) >> 5) as u8
}
pub fn supplemental_data_mpda_cut(&self) -> bool {
((self.supplemental_data & 0x0200) >> 9) == 1
}
pub fn supplemental_data_base_tilt_cut(&self) -> bool {
((self.supplemental_data & 0x0400) >> 10) == 1
}
}
impl Debug for ElevationDataBlock {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut debug = f.debug_struct("ElevationDataBlock");
#[cfg(feature = "uom")]
debug.field("elevation_angle", &self.elevation_angle());
#[cfg(not(feature = "uom"))]
debug.field("elevation_angle", &self.elevation_angle_degrees());
debug.field("channel_configuration", &self.channel_configuration());
debug.field("waveform_type", &self.waveform_type());
debug.field(
"super_resolution_control_raw",
&self.super_resolution_control,
);
debug.field(
"super_resolution_control_half_degree_azimuth",
&self.super_resolution_control_half_degree_azimuth(),
);
debug.field(
"super_resolution_control_quarter_km_reflectivity",
&self.super_resolution_control_quarter_km_reflectivity(),
);
debug.field(
"super_resolution_control_doppler_to_300km",
&self.super_resolution_control_doppler_to_300km(),
);
debug.field(
"super_resolution_control_dual_polarization_to_300km",
&self.super_resolution_control_dual_polarization_to_300km(),
);
debug.field("surveillance_prf_number", &self.surveillance_prf_number);
debug.field(
"surveillance_prf_pulse_count_radial",
&self.surveillance_prf_pulse_count_radial,
);
#[cfg(feature = "uom")]
debug.field("azimuth_rate", &self.azimuth_rate());
#[cfg(not(feature = "uom"))]
debug.field("azimuth_rate", &self.azimuth_rate_degrees_per_second());
debug.field("reflectivity_threshold", &self.reflectivity_threshold());
debug.field("velocity_threshold", &self.velocity_threshold());
debug.field("spectrum_width_threshold", &self.spectrum_width_threshold());
debug.field(
"differential_reflectivity_threshold",
&self.differential_reflectivity_threshold(),
);
debug.field(
"differential_phase_threshold",
&self.differential_phase_threshold(),
);
debug.field(
"correlation_coefficient_threshold",
&self.correlation_coefficient_threshold(),
);
#[cfg(feature = "uom")]
debug.field("sector_1_edge_angle", &self.sector_1_edge_angle());
#[cfg(not(feature = "uom"))]
debug.field("sector_1_edge_angle", &self.sector_1_edge_angle_degrees());
debug.field(
"sector_1_doppler_prf_number",
&self.sector_1_doppler_prf_number,
);
debug.field(
"sector_1_doppler_prf_pulse_count_radial",
&self.sector_1_doppler_prf_pulse_count_radial,
);
#[cfg(feature = "uom")]
debug.field("sector_2_edge_angle", &self.sector_2_edge_angle());
#[cfg(not(feature = "uom"))]
debug.field("sector_2_edge_angle", &self.sector_2_edge_angle_degrees());
debug.field(
"sector_2_doppler_prf_number",
&self.sector_2_doppler_prf_number,
);
debug.field(
"sector_2_doppler_prf_pulse_count_radial",
&self.sector_2_doppler_prf_pulse_count_radial,
);
#[cfg(feature = "uom")]
debug.field("sector_3_edge_angle", &self.sector_3_edge_angle());
#[cfg(not(feature = "uom"))]
debug.field("sector_3_edge_angle", &self.sector_3_edge_angle_degrees());
debug.field(
"sector_3_doppler_prf_number",
&self.sector_3_doppler_prf_number,
);
debug.field(
"sector_3_doppler_prf_pulse_count_radial",
&self.sector_3_doppler_prf_pulse_count_radial,
);
#[cfg(feature = "uom")]
debug.field("ebc_angle", &self.ebc_angle());
#[cfg(not(feature = "uom"))]
debug.field("ebc_angle", &self.ebc_angle_degrees());
debug.field("supplemental_data", &self.supplemental_data);
debug.field(
"supplemental_data_sails_cut",
&self.supplemental_data_sails_cut(),
);
debug.field(
"supplemental_data_sails_sequence_number",
&self.supplemental_data_sails_sequence_number(),
);
debug.field(
"supplemental_data_mrle_cut",
&self.supplemental_data_mrle_cut(),
);
debug.field(
"supplemental_data_mrle_sequence_number",
&self.supplemental_data_mrle_sequence_number(),
);
debug.field(
"supplemental_data_mpda_cut",
&self.supplemental_data_mpda_cut(),
);
debug.field(
"supplemental_data_base_tilt_cut",
&self.supplemental_data_base_tilt_cut(),
);
debug.field("reserved", &self.reserved);
debug.finish()
}
}