From 638d135226dfbf51ca038291f64a0c359ca49454 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 13 May 2022 05:22:26 +0200 Subject: [PATCH 01/17] Add missing debug implementations. --- ublox_derive/src/types.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ublox_derive/src/types.rs b/ublox_derive/src/types.rs index f9b9c9a..94a0bad 100644 --- a/ublox_derive/src/types.rs +++ b/ublox_derive/src/types.rs @@ -55,6 +55,7 @@ impl PayloadLen { } } +#[derive(Debug)] pub struct PackField { pub name: Ident, pub ty: Type, @@ -63,6 +64,7 @@ pub struct PackField { pub size_bytes: Option, } +#[derive(Debug)] pub struct PackFieldMapDesc { pub map_type: Option, pub scale: Option, @@ -71,6 +73,7 @@ pub struct PackFieldMapDesc { pub get_as_ref: bool, } +#[derive(Debug)] pub struct MapTypeDesc { pub ty: Type, pub from_fn: TokenStream, From ca9cebdc246156cb637129af0e675fa56ce24e01 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 13 May 2022 07:37:31 +0200 Subject: [PATCH 02/17] Add `CfgValSet`. --- ublox/src/ubx_packets.rs | 1 + ublox/src/ubx_packets/cfg_val.rs | 245 +++++++++++++++++++++++++++++++ ublox/src/ubx_packets/packets.rs | 76 +++++++++- ublox_derive/src/output.rs | 88 ++++++++--- 4 files changed, 389 insertions(+), 21 deletions(-) create mode 100644 ublox/src/ubx_packets/cfg_val.rs diff --git a/ublox/src/ubx_packets.rs b/ublox/src/ubx_packets.rs index 05ae3bb..7cb7127 100644 --- a/ublox/src/ubx_packets.rs +++ b/ublox/src/ubx_packets.rs @@ -1,3 +1,4 @@ +pub mod cfg_val; mod packets; mod types; diff --git a/ublox/src/ubx_packets/cfg_val.rs b/ublox/src/ubx_packets/cfg_val.rs new file mode 100644 index 0000000..61f9868 --- /dev/null +++ b/ublox/src/ubx_packets/cfg_val.rs @@ -0,0 +1,245 @@ +use super::{CfgInfMask, DataBits, Parity, StopBits}; + +pub struct KeyId(u32); + +pub enum StorageSize { + OneBit, + OneByte, + TwoBytes, + FourBytes, + EightBytes, +} + +impl StorageSize { + pub const fn to_usize(self) -> usize { + match self { + Self::OneBit | Self::OneByte => 1, + Self::TwoBytes => 2, + Self::FourBytes => 4, + Self::EightBytes => 8, + } + } +} + +impl KeyId { + pub(crate) const SIZE: usize = 4; + + pub const fn value_size(&self) -> StorageSize { + match (self.0 >> 28) & 0b111 { + 1 => StorageSize::OneBit, + 2 => StorageSize::OneByte, + 3 => StorageSize::TwoBytes, + 4 => StorageSize::FourBytes, + 5 => StorageSize::EightBytes, + _ => unreachable!(), + } + } + + pub const fn group_id(&self) -> u8 { + (self.0 >> 16) as u8 + } + + pub const fn item_id(&self) -> u8 { + self.0 as u8 + } +} + +macro_rules! from_cfg_v_bytes { + ($buf:expr, bool) => { + match $buf[0] { + 0 => false, + 1 => true, + _ => unreachable!(), + } + }; + ($buf:expr, u32) => { + u32::from_le_bytes([$buf[0], $buf[1], $buf[2], $buf[3]]) + }; + ($buf:expr, CfgInfMask) => { + CfgInfMask::from_bits_truncate($buf[0]) + }; + ($buf:expr, DataBits) => { + match $buf[0] { + 0 => DataBits::Eight, + 1 => DataBits::Seven, + _ => unreachable!(), + } + }; + ($buf:expr, Parity) => { + match $buf[0] { + 0 => Parity::None, + 1 => Parity::Odd, + 2 => Parity::Even, + _ => unreachable!(), + } + }; + ($buf:expr, StopBits) => { + match $buf[0] { + 0 => StopBits::Half, + 1 => StopBits::One, + 2 => StopBits::OneHalf, + 3 => StopBits::Two, + _ => unreachable!(), + } + }; +} + +macro_rules! into_cfg_kv_bytes { + (@inner [$($byte:expr),+]) => {{ + let key_id = Self::KEY.0.to_le_bytes(); + + [ + key_id[0], key_id[1], key_id[2], key_id[3], + $( + $byte, + )* + ] + }}; + ($this:expr, bool) => { + into_cfg_kv_bytes!(@inner [$this.0 as u8]) + }; + ($this:expr, u32) => {{ + let bytes = $this.0.to_le_bytes(); + into_cfg_kv_bytes!(@inner [bytes[0], bytes[1], bytes[2], bytes[3]]) + }}; + ($this:expr, CfgInfMask) => { + into_cfg_kv_bytes!(@inner [ + $this.0.bits() + ]) + }; + ($this:expr, DataBits) => { + into_cfg_kv_bytes!(@inner [ + match $this.0 { + DataBits::Eight => 0, + DataBits::Seven => 1, + } + ]) + }; + ($this:expr, Parity) => { + into_cfg_kv_bytes!(@inner [ + match $this.0 { + Parity::None => 0, + Parity::Odd => 1, + Parity::Even => 2, + } + ]) + }; + ($this:expr, StopBits) => { + into_cfg_kv_bytes!(@inner [ + match $this.0 { + StopBits::Half => 0, + StopBits::One => 1, + StopBits::OneHalf => 2, + StopBits::Two => 3, + } + ]) + }; +} + +macro_rules! cfg_val { + ($($cfg_item:ident, $cfg_key_id:expr, $cfg_value_type:ident,)*) => { + #[derive(Debug, Clone, Copy)] + pub enum CfgVal { + $( + $cfg_item($cfg_value_type), + )* + } + + impl CfgVal { + pub const fn len(&self) -> usize { + match self { + $( + Self::$cfg_item(value) => { + $cfg_item::SIZE + } + )* + } + } + + #[track_caller] + pub fn parse(buf: &[u8]) -> Self { + let key_id = u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]); + match key_id { + $( + $cfg_key_id => { + Self::$cfg_item(from_cfg_v_bytes!(&buf[4..], $cfg_value_type)) + }, + )* + _ => unimplemented!("unknown key ID: 0x{:8X}", key_id), + } + } + + pub fn extend_to(&self, buf: &mut T) -> usize + where + T: core::iter::Extend + { + match self { + $( + Self::$cfg_item(value) => { + let bytes = $cfg_item(*value).into_cfg_kv_bytes(); + let bytes_len = bytes.len(); + buf.extend(bytes); + bytes_len + } + )* + } + } + + pub fn write_to(&self, buf: &mut [u8]) -> usize { + match self { + $( + Self::$cfg_item(value) => { + let kv: [u8; $cfg_item::SIZE] = $cfg_item(*value).into_cfg_kv_bytes(); + buf[..kv.len()].copy_from_slice(&kv[..]); + kv.len() + } + )* + } + } + } + + $( + struct $cfg_item(pub $cfg_value_type); + + impl $cfg_item { + const KEY: KeyId = KeyId($cfg_key_id); + const SIZE: usize = KeyId::SIZE + Self::KEY.value_size().to_usize(); + + pub const fn into_cfg_kv_bytes(self) -> [u8; Self::SIZE] { + into_cfg_kv_bytes!(self, $cfg_value_type) + } + } + )* + } +} + +cfg_val! { + // CFG-UART1 + Uart1Baudrate, 0x40520001, u32, + Uart1StopBits, 0x20520002, StopBits, + Uart1DataBits, 0x20520003, DataBits, + Uart1Parity, 0x20520004, Parity, + Uart1Enabled, 0x10520005, bool, + + // CFG-UART1INPROT + Uart1InProtUbx, 0x10730001, bool, + Uart1InProtNmea, 0x10730002, bool, + Uart1InProtRtcm3x, 0x10730004, bool, + + // CFG-UART1OUTPROT + Uart1OutProtUbx, 0x10740001, bool, + Uart1OutProtNmea, 0x10740002, bool, + Uart1OutProtRtcm3x, 0x10740004, bool, + + // CFG-INFMSG + InfmsgUbxI2c, 0x20920001, CfgInfMask, + InfmsgUbxUart1, 0x20920002, CfgInfMask, + InfmsgUbxUart2, 0x20920003, CfgInfMask, + InfmsgUbxUsb, 0x20920004, CfgInfMask, + InfmsgUbxSpi, 0x20920005, CfgInfMask, + InfmsgNmeaI2c, 0x20920006, CfgInfMask, + InfmsgNmeaUart1, 0x20920007, CfgInfMask, + InfmsgNmeaUart2, 0x20920008, CfgInfMask, + InfmsgNmeaUsb, 0x20920009, CfgInfMask, + InfmsgNmeaSpi, 0x2092000a, CfgInfMask, +} diff --git a/ublox/src/ubx_packets/packets.rs b/ublox/src/ubx_packets/packets.rs index db2e0ad..29272f9 100644 --- a/ublox/src/ubx_packets/packets.rs +++ b/ublox/src/ubx_packets/packets.rs @@ -2,6 +2,7 @@ use super::{ ubx_checksum, MemWriter, Position, UbxChecksumCalc, UbxPacketCreator, UbxPacketMeta, UbxUnknownPacketRef, SYNC_CHAR_1, SYNC_CHAR_2, }; +use crate::cfg_val::CfgVal; use crate::error::{MemWriterError, ParserError}; use bitflags::bitflags; use chrono::prelude::*; @@ -758,8 +759,8 @@ bitflags! { const ERROR = 0x1; const WARNING = 0x2; const NOTICE = 0x4; - const DEBUG = 0x08; - const TEST = 0x10; + const TEST = 0x08; + const DEBUG = 0x10; } } @@ -1055,6 +1056,77 @@ impl ResetMode { } } +#[ubx_packet_send] +#[ubx( + class = 0x06, + id = 0x8a, + max_payload_len = 772, // 4 + (4 + 8) * 64 +)] +struct CfgValSet { + /// Message version + version: u8, + /// The layers from which the configuration items should be retrieved + #[ubx(map_type = CfgLayer)] + layers: u8, + reserved1: [u8; 2], + #[ubx(map_type = CfgValIter<'a>)] + cfg_data: [u8; 0], +} + +#[derive(Debug, Clone)] +pub struct CfgValIter<'a> { + pub(crate) data: &'a [u8], + pub(crate) offset: usize, +} + +impl<'a> CfgValIter<'a> { + pub fn new(data: &'a mut [u8], values: &[CfgVal]) -> Self { + let mut offset = 0; + + for value in values { + offset += value.write_to(&mut data[offset..]); + } + + Self { + data: &data[..offset], + offset: 0, + } + } +} + +impl<'a> core::iter::Iterator for CfgValIter<'a> { + type Item = CfgVal; + + fn next(&mut self) -> Option { + if self.offset < self.data.len() { + let cfg_val = CfgVal::parse(&self.data[self.offset..]); + + self.offset += cfg_val.len(); + + Some(cfg_val) + } else { + None + } + } +} + +#[ubx_extend_bitflags] +#[ubx(from, into_raw, rest_reserved)] +bitflags! { + /// A mask describing where configuration is applied. + pub struct CfgLayer: u8 { + const RAM = 0b001; + const BBR = 0b010; + const FLASH = 0b100; + } +} + +impl Default for CfgLayer { + fn default() -> Self { + Self::RAM | Self::BBR | Self::FLASH + } +} + /// Port Configuration for I2C #[ubx_packet_recv_send] #[ubx( diff --git a/ublox_derive/src/output.rs b/ublox_derive/src/output.rs index ea86836..f341b1f 100644 --- a/ublox_derive/src/output.rs +++ b/ublox_derive/src/output.rs @@ -214,9 +214,12 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { let main_name = Ident::new(&pack_descr.name, Span::call_site()); let payload_struct = format_ident!("{}Builder", pack_descr.name); + let mut builder_needs_lifetime = false; + let mut fields = Vec::with_capacity(pack_descr.fields.len()); let mut pack_fields = Vec::with_capacity(pack_descr.fields.len()); let mut write_fields = Vec::with_capacity(pack_descr.fields.len()); + let mut extend_fields = Vec::with_capacity(pack_descr.fields.len()); let mut off = 6usize; for f in &pack_descr.fields { let ty = f.intermediate_type(); @@ -227,21 +230,31 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { pub #name: #ty }); let size_bytes = match f.size_bytes { - Some(x) => x, - None => unimplemented!(), + Some(x) => x.get(), + None => 0, }; - if let Some(into_fn) = f.map.map_type.as_ref().map(|x| &x.into_fn) { - pack_fields.push(quote! { - let bytes = #into_fn(self.#name).to_le_bytes() - }); - } else if !f.is_field_raw_ty_byte_array() { + + if size_bytes == 0 { + // Iterator with `data` field. pack_fields.push(quote! { - let bytes = self.#name.to_le_bytes() + let bytes: &[u8] = self.#name.data; }); + + builder_needs_lifetime = true; } else { - pack_fields.push(quote! { - let bytes: &[u8] = &self.#name; - }); + if let Some(into_fn) = f.map.map_type.as_ref().map(|x| &x.into_fn) { + pack_fields.push(quote! { + let bytes = #into_fn(self.#name).to_le_bytes() + }); + } else if !f.is_field_raw_ty_byte_array() { + pack_fields.push(quote! { + let bytes = self.#name.to_le_bytes() + }); + } else { + pack_fields.push(quote! { + let bytes: &[u8] = &self.#name; + }); + } } write_fields.push(pack_fields.last().unwrap().clone()); @@ -249,14 +262,21 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { out.write(&bytes)?; checksum_calc.update(&bytes) }); - for i in 0..size_bytes.get() { + + extend_fields.push(pack_fields.last().unwrap().clone()); + extend_fields.push(quote! { + len_bytes += bytes.len(); + out.extend(bytes.into_iter().cloned()); + }); + + for i in 0..size_bytes { let byte_off = off.checked_add(i).unwrap(); pack_fields.push(quote! { ret[#byte_off] = bytes[#i] }); } - off += size_bytes.get(); + off += size_bytes; } let builder_attr = if pack_descr .header @@ -269,11 +289,18 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { quote! {} }; let struct_comment = &pack_descr.comment; + + let payload_struct_lifetime = if builder_needs_lifetime { + quote! { <'a> } + } else { + quote! {} + }; + let mut ret = quote! { #[doc = #struct_comment] #[doc = "Struct that is used to construct packets, see the crate-level documentation for more information"] #builder_attr - pub struct #payload_struct { + pub struct #payload_struct #payload_struct_lifetime { #(#fields),* } }; @@ -282,7 +309,7 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { let packet_size = packet_payload_size + 8; let packet_payload_size_u16 = u16::try_from(packet_payload_size).unwrap(); ret.extend(quote! { - impl #payload_struct { + impl #payload_struct_lifetime #payload_struct #payload_struct_lifetime { pub const PACKET_LEN: usize = #packet_size; #[inline] @@ -296,9 +323,9 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { ret[4] = pack_len_bytes[0]; ret[5] = pack_len_bytes[1]; #(#pack_fields);*; - let (ck_a, ck_b) = ubx_checksum(&ret[2..#packet_size-2]); - ret[#packet_size-2] = ck_a; - ret[#packet_size-1] = ck_b; + let (ck_a, ck_b) = ubx_checksum(&ret[2..(Self::PACKET_LEN - 2)]); + ret[Self::PACKET_LEN - 2] = ck_a; + ret[Self::PACKET_LEN - 1] = ck_b; ret } } @@ -325,7 +352,30 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { } }); } else { - unimplemented!(); + ret.extend(quote! { + impl #payload_struct_lifetime #payload_struct #payload_struct_lifetime { + #[inline] + pub fn extend_to(self, out: &mut T) + where + T: core::iter::Extend + + core::ops::DerefMut + { + // TODO: Enable when `extend_one` feature is stable. + // out.extend_reserve(6); + let mut len_bytes = 0; + let header = [SYNC_CHAR_1, SYNC_CHAR_2, #main_name::CLASS, #main_name::ID, 0, 0]; + out.extend(header); + #(#extend_fields);*; + + let len_bytes = len_bytes.to_le_bytes(); + out[4] = len_bytes[0]; + out[5] = len_bytes[1]; + + let (ck_a, ck_b) = ubx_checksum(&out[2..]); + out.extend([ck_a, ck_b]); + } + } + }) } ret From 849c0bd83bed52015233a1b55058a5265d143241 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 13 May 2022 09:01:57 +0200 Subject: [PATCH 03/17] Use reference instead of iterator. --- ublox/src/ubx_packets/cfg_val.rs | 101 ++++++++++++++++++++++++------- ublox/src/ubx_packets/packets.rs | 8 ++- ublox_derive/src/input.rs | 2 + ublox_derive/src/output.rs | 7 ++- 4 files changed, 91 insertions(+), 27 deletions(-) diff --git a/ublox/src/ubx_packets/cfg_val.rs b/ublox/src/ubx_packets/cfg_val.rs index 61f9868..434d6e9 100644 --- a/ublox/src/ubx_packets/cfg_val.rs +++ b/ublox/src/ubx_packets/cfg_val.rs @@ -1,4 +1,4 @@ -use super::{CfgInfMask, DataBits, Parity, StopBits}; +use super::{AlignmentToReferenceTime, CfgInfMask, DataBits, Parity, StopBits}; pub struct KeyId(u32); @@ -52,6 +52,12 @@ macro_rules! from_cfg_v_bytes { _ => unreachable!(), } }; + ($buf:expr, u8) => { + $buf[0] + }; + ($buf:expr, u16) => { + u16::from_le_bytes([$buf[0], $buf[1]]) + }; ($buf:expr, u32) => { u32::from_le_bytes([$buf[0], $buf[1], $buf[2], $buf[3]]) }; @@ -82,6 +88,16 @@ macro_rules! from_cfg_v_bytes { _ => unreachable!(), } }; + ($buf:expr, AlignmentToReferenceTime) => { + match $buf[0] { + 0 => AlignmentToReferenceTime::Utc, + 1 => AlignmentToReferenceTime::Gps, + 2 => AlignmentToReferenceTime::Glo, + 3 => AlignmentToReferenceTime::Bds, + 4 => AlignmentToReferenceTime::Gal, + _ => unreachable!(), + } + }; } macro_rules! into_cfg_kv_bytes { @@ -98,6 +114,13 @@ macro_rules! into_cfg_kv_bytes { ($this:expr, bool) => { into_cfg_kv_bytes!(@inner [$this.0 as u8]) }; + ($this:expr, u8) => {{ + into_cfg_kv_bytes!(@inner [$this.0]) + }}; + ($this:expr, u16) => {{ + let bytes = $this.0.to_le_bytes(); + into_cfg_kv_bytes!(@inner [bytes[0], bytes[1]]) + }}; ($this:expr, u32) => {{ let bytes = $this.0.to_le_bytes(); into_cfg_kv_bytes!(@inner [bytes[0], bytes[1], bytes[2], bytes[3]]) @@ -134,6 +157,11 @@ macro_rules! into_cfg_kv_bytes { } ]) }; + ($this:expr, AlignmentToReferenceTime) => { + into_cfg_kv_bytes!(@inner [ + $this.0 as u8 + ]) + } } macro_rules! cfg_val { @@ -215,31 +243,60 @@ macro_rules! cfg_val { cfg_val! { // CFG-UART1 - Uart1Baudrate, 0x40520001, u32, - Uart1StopBits, 0x20520002, StopBits, - Uart1DataBits, 0x20520003, DataBits, - Uart1Parity, 0x20520004, Parity, - Uart1Enabled, 0x10520005, bool, + Uart1Baudrate, 0x40520001, u32, + Uart1StopBits, 0x20520002, StopBits, + Uart1DataBits, 0x20520003, DataBits, + Uart1Parity, 0x20520004, Parity, + Uart1Enabled, 0x10520005, bool, // CFG-UART1INPROT - Uart1InProtUbx, 0x10730001, bool, - Uart1InProtNmea, 0x10730002, bool, - Uart1InProtRtcm3x, 0x10730004, bool, + Uart1InProtUbx, 0x10730001, bool, + Uart1InProtNmea, 0x10730002, bool, + Uart1InProtRtcm3x, 0x10730004, bool, // CFG-UART1OUTPROT - Uart1OutProtUbx, 0x10740001, bool, - Uart1OutProtNmea, 0x10740002, bool, - Uart1OutProtRtcm3x, 0x10740004, bool, + Uart1OutProtUbx, 0x10740001, bool, + Uart1OutProtNmea, 0x10740002, bool, + Uart1OutProtRtcm3x, 0x10740004, bool, // CFG-INFMSG - InfmsgUbxI2c, 0x20920001, CfgInfMask, - InfmsgUbxUart1, 0x20920002, CfgInfMask, - InfmsgUbxUart2, 0x20920003, CfgInfMask, - InfmsgUbxUsb, 0x20920004, CfgInfMask, - InfmsgUbxSpi, 0x20920005, CfgInfMask, - InfmsgNmeaI2c, 0x20920006, CfgInfMask, - InfmsgNmeaUart1, 0x20920007, CfgInfMask, - InfmsgNmeaUart2, 0x20920008, CfgInfMask, - InfmsgNmeaUsb, 0x20920009, CfgInfMask, - InfmsgNmeaSpi, 0x2092000a, CfgInfMask, + InfmsgUbxI2c, 0x20920001, CfgInfMask, + InfmsgUbxUart1, 0x20920002, CfgInfMask, + InfmsgUbxUart2, 0x20920003, CfgInfMask, + InfmsgUbxUsb, 0x20920004, CfgInfMask, + InfmsgUbxSpi, 0x20920005, CfgInfMask, + InfmsgNmeaI2c, 0x20920006, CfgInfMask, + InfmsgNmeaUart1, 0x20920007, CfgInfMask, + InfmsgNmeaUart2, 0x20920008, CfgInfMask, + InfmsgNmeaUsb, 0x20920009, CfgInfMask, + InfmsgNmeaSpi, 0x2092000a, CfgInfMask, + + // CFG-RATE-* + RateMeas, 0x30210001, u16, + RateNav, 0x30210002, u16, + RateTimeref, 0x20210003, AlignmentToReferenceTime, + + // CFG-MSGOUT-* + MsgoutUbxRxmRawxI2x, 0x209102a4, u8, + MsgoutUbxRxmRawxSpi, 0x209102a8, u8, + MsgoutUbxRxmRawxUart1, 0x209102a5, u8, + MsgoutUbxRxmRawxUart2, 0x209102a6, u8, + MsgoutUbxRxmRawxUsb, 0x209102a7, u8, + + // CFG-SIGNAL-* + SignalGpsEna, 0x1031001f, bool, + SignalGpsL1caEna, 0x10310001, bool, + SignalGpsL2cEna, 0x10310003, bool, + SignalGalEna, 0x10310021, bool, + SignalGalE1Ena, 0x10310007, bool, + SignalGalE5bEna, 0x1031000a, bool, + SignalBdsEna, 0x10310022, bool, + SignalBdsB1Ena, 0x1031000d, bool, + SignalBdsB2Ena, 0x1031000e, bool, + SignalQzssEna, 0x10310024, bool, + SignalQzssL1caEna, 0x10310012, bool, + SignalQzssL2cEna, 0x10310015, bool, + SignalGloEna, 0x10310025, bool, + SignalGloL1Ena, 0x10310018, bool, + SignalGLoL2Ena, 0x1031001a, bool, } diff --git a/ublox/src/ubx_packets/packets.rs b/ublox/src/ubx_packets/packets.rs index 29272f9..23c3ccf 100644 --- a/ublox/src/ubx_packets/packets.rs +++ b/ublox/src/ubx_packets/packets.rs @@ -1062,15 +1062,14 @@ impl ResetMode { id = 0x8a, max_payload_len = 772, // 4 + (4 + 8) * 64 )] -struct CfgValSet { +struct CfgValSet<'a> { /// Message version version: u8, /// The layers from which the configuration items should be retrieved #[ubx(map_type = CfgLayer)] layers: u8, reserved1: [u8; 2], - #[ubx(map_type = CfgValIter<'a>)] - cfg_data: [u8; 0], + cfg_data: &'a [CfgVal], } #[derive(Debug, Clone)] @@ -1474,6 +1473,9 @@ struct CfgRate { pub enum AlignmentToReferenceTime { Utc = 0, Gps = 1, + Glo = 2, + Bds = 3, + Gal = 4, } impl AlignmentToReferenceTime { diff --git a/ublox_derive/src/input.rs b/ublox_derive/src/input.rs index acee075..de4ae8e 100644 --- a/ublox_derive/src/input.rs +++ b/ublox_derive/src/input.rs @@ -576,6 +576,8 @@ fn field_size_bytes(ty: &Type) -> syn::Result> { "Can not interpret array length", )) } + } else if let syn::Type::Reference(ref reference) = ty { + Ok(None) } else { let mut valid_type_names = String::with_capacity(200); for (t, _) in &valid_types { diff --git a/ublox_derive/src/output.rs b/ublox_derive/src/output.rs index f341b1f..bf54e9f 100644 --- a/ublox_derive/src/output.rs +++ b/ublox_derive/src/output.rs @@ -236,11 +236,14 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { if size_bytes == 0 { // Iterator with `data` field. - pack_fields.push(quote! { - let bytes: &[u8] = self.#name.data; + extend_fields.push(quote! { + for f in self.#name { + len_bytes += f.extend_to(out); + } }); builder_needs_lifetime = true; + continue; } else { if let Some(into_fn) = f.map.map_type.as_ref().map(|x| &x.into_fn) { pack_fields.push(quote! { From 5e1cb51e8303d03816d6adc48b2387193f7e6740 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 14 May 2022 23:06:01 +0200 Subject: [PATCH 04/17] Add `as_bytes` method for `PacketRef` types. --- ublox_derive/src/output.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ublox_derive/src/output.rs b/ublox_derive/src/output.rs index bf54e9f..376a6c1 100644 --- a/ublox_derive/src/output.rs +++ b/ublox_derive/src/output.rs @@ -175,6 +175,10 @@ pub fn generate_recv_code_for_packet(pack_descr: &PackDesc) -> TokenStream { #[doc = "Contains a reference to an underlying buffer, contains accessor methods to retrieve data."] pub struct #ref_name<'a>(&'a [u8]); impl<'a> #ref_name<'a> { + pub fn as_bytes(&self) -> &[u8] { + self.0 + } + #(#getters)* #validator From a8e1d04570f7be49c257a631b2553869c0cd93aa Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 15 May 2022 00:03:41 +0200 Subject: [PATCH 05/17] Add `RxmRawx` packet. --- ublox/src/ubx_packets/packets.rs | 109 +++++++++++++++++++++++++++++++ ublox_derive/src/input.rs | 3 +- 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/ublox/src/ubx_packets/packets.rs b/ublox/src/ubx_packets/packets.rs index 23c3ccf..f0a50e2 100644 --- a/ublox/src/ubx_packets/packets.rs +++ b/ublox/src/ubx_packets/packets.rs @@ -1899,6 +1899,114 @@ pub enum MsgAckInfoCode { RejectedUnknownType = 6, } +#[ubx_packet_recv] +#[ubx(class = 0x02, id = 0x15, max_payload_len = 8176)] // 16 + 255 * 32 +struct RxmRawx { + /// Measurement time of week in receiver local time approximately aligned to the GPS time system. + rcv_tow: f64, + /// GPS week number in receiver local time. + week: u16, + /// GPS leap seconds (GPS-UTC) + leap_s: i8, + /// Number of measurements to follow + num_meas: u8, + /// Receiver tracking status bitfield + #[ubx(map_type = RecStat)] + rec_stat: u8, + /// Message version + version: u8, + reserved1: [u8; 2], + /// Extended software information strings + #[ubx(map_type = MeasurementIter, may_fail, + from = Measurement::to_iter, + is_valid = Measurement::is_valid)] + measurements: [u8; 0], +} + +#[ubx_extend_bitflags] +#[ubx(from, into_raw, rest_reserved)] +bitflags! { + /// `CfgNavX5Params2` parameters bitmask + #[derive(Default)] + pub struct RecStat: u8 { + /// Leap seconds have been determined + const LEAP_SEC = 0x1; + /// Clock reset applied. + const CLK_RESET = 0x2; + } +} + +#[derive(Debug, Clone)] +pub struct MeasurementIter<'a> { + data: &'a [u8], + offset: usize, +} + +#[derive(Debug, Clone)] +pub struct Measurement { + pr_mes: f64, + cp_mes: f64, + do_mes: f32, + gnss_id: u8, + sv_id: u8, + sig_id: u8, + freq_id: u8, + lock_time: u16, + cno: u8, + pr_stdev: u8, + cp_stdev: u8, + do_stdev: u8, + trk_stat: u8, + reserved2: u8, +} + +impl Measurement { + pub(crate) fn is_valid(payload: &[u8]) -> bool { + payload.len() % 32 == 0 + } + + pub(crate) fn to_iter(payload: &[u8]) -> MeasurementIter { + MeasurementIter { + data: payload, + offset: 0, + } + } +} + +impl<'a> core::iter::Iterator for MeasurementIter<'a> { + type Item = Measurement; + + fn next(&mut self) -> Option { + if self.offset < self.data.len() { + let data = &self.data[self.offset..(self.offset + 32)]; + self.offset += 32; + + Some(Measurement { + pr_mes: f64::from_le_bytes([ + data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], + ]), + cp_mes: f64::from_le_bytes([ + data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15], + ]), + do_mes: f32::from_le_bytes([data[16], data[17], data[18], data[19]]), + gnss_id: data[20], + sv_id: data[21], + sig_id: data[22], + freq_id: data[23], + lock_time: u16::from_le_bytes([data[24], data[25]]), + cno: data[26], + pr_stdev: data[27], + cp_stdev: data[28], + do_stdev: data[29], + trk_stat: data[30], + reserved2: data[31], + }) + } else { + None + } + } +} + /// Hardware status #[ubx_packet_recv] #[ubx(class = 0x0a, id = 0x09, fixed_payload_len = 60)] @@ -2069,6 +2177,7 @@ define_recv_packets!( InfNotice, InfTest, InfDebug, + RxmRawx, MonVer, MonHw, RxmRtcm diff --git a/ublox_derive/src/input.rs b/ublox_derive/src/input.rs index de4ae8e..cf8f761 100644 --- a/ublox_derive/src/input.rs +++ b/ublox_derive/src/input.rs @@ -549,13 +549,14 @@ impl Parse for Comment { fn field_size_bytes(ty: &Type) -> syn::Result> { //TODO: make this array static //TODO: support f32, f64 - let valid_types: [(Type, NonZeroUsize); 6] = [ + let valid_types: [(Type, NonZeroUsize); 7] = [ (syn::parse_quote!(u8), NonZeroUsize::new(1).unwrap()), (syn::parse_quote!(i8), NonZeroUsize::new(1).unwrap()), (syn::parse_quote!(u16), NonZeroUsize::new(2).unwrap()), (syn::parse_quote!(i16), NonZeroUsize::new(2).unwrap()), (syn::parse_quote!(u32), NonZeroUsize::new(4).unwrap()), (syn::parse_quote!(i32), NonZeroUsize::new(4).unwrap()), + (syn::parse_quote!(f64), NonZeroUsize::new(8).unwrap()), ]; if let Some((_ty, size)) = valid_types.iter().find(|x| x.0 == *ty) { Ok(Some(*size)) From d9b3be47637b8724e25be2d36ccee26d32844c82 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 1 Jun 2022 00:42:51 +0200 Subject: [PATCH 06/17] Add more config values. --- ublox/src/ubx_packets/cfg_val.rs | 140 ++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) diff --git a/ublox/src/ubx_packets/cfg_val.rs b/ublox/src/ubx_packets/cfg_val.rs index 434d6e9..9afdcd2 100644 --- a/ublox/src/ubx_packets/cfg_val.rs +++ b/ublox/src/ubx_packets/cfg_val.rs @@ -58,6 +58,9 @@ macro_rules! from_cfg_v_bytes { ($buf:expr, u16) => { u16::from_le_bytes([$buf[0], $buf[1]]) }; + ($buf:expr, i16) => { + i16::from_le_bytes([$buf[0], $buf[1]]) + }; ($buf:expr, u32) => { u32::from_le_bytes([$buf[0], $buf[1], $buf[2], $buf[3]]) }; @@ -98,6 +101,20 @@ macro_rules! from_cfg_v_bytes { _ => unreachable!(), } }; + ($buf:expr, TpPulse) => { + match $buf[0] { + 0 => TpPulse::Period, + 1 => TpPulse::Freq, + _ => unreachable!(), + } + }; + ($buf:expr, TpPulseLength) => { + match $buf[0] { + 0 => TpPulseLength::Ratio, + 1 => TpPulseLength::Length, + _ => unreachable!(), + } +}; } macro_rules! into_cfg_kv_bytes { @@ -121,6 +138,10 @@ macro_rules! into_cfg_kv_bytes { let bytes = $this.0.to_le_bytes(); into_cfg_kv_bytes!(@inner [bytes[0], bytes[1]]) }}; + ($this:expr, i16) => {{ + let bytes = $this.0.to_le_bytes(); + into_cfg_kv_bytes!(@inner [bytes[0], bytes[1]]) + }}; ($this:expr, u32) => {{ let bytes = $this.0.to_le_bytes(); into_cfg_kv_bytes!(@inner [bytes[0], bytes[1], bytes[2], bytes[3]]) @@ -159,9 +180,19 @@ macro_rules! into_cfg_kv_bytes { }; ($this:expr, AlignmentToReferenceTime) => { into_cfg_kv_bytes!(@inner [ - $this.0 as u8 + $this.0 as u8 ]) - } + }; + ($this:expr, TpPulse) => { + into_cfg_kv_bytes!(@inner [ + $this.0 as u8 + ]) + }; + ($this:expr, TpPulseLength) => { + into_cfg_kv_bytes!(@inner [ + $this.0 as u8 + ]) + }; } macro_rules! cfg_val { @@ -277,12 +308,84 @@ cfg_val! { RateTimeref, 0x20210003, AlignmentToReferenceTime, // CFG-MSGOUT-* + MsgoutNmeaIdGgaI2c, 0x209100ba, u8, + MsgoutNmeaIdGgaSpi, 0x209100be, u8, + MsgoutNmeaIdGgaUart1, 0x209100bb, u8, + MsgoutNmeaIdGgaUart2, 0x209100bc, u8, + MsgoutNmeaIdGgaUsb, 0x209100bd, u8, + + MsgoutNmeaIdGllI2c, 0x209100c9, u8, + MsgoutNmeaIdGllSpi, 0x209100cd, u8, + MsgoutNmeaIdGllUart1, 0x209100ca, u8, + MsgoutNmeaIdGllUart2, 0x209100cb, u8, + MsgoutNmeaIdGllUsb, 0x209100cc, u8, + + MsgoutNmeaIdGnsI2c, 0x209100b5, u8, + MsgoutNmeaIdGnsSpi, 0x209100b9, u8, + MsgoutNmeaIdGnsUart1, 0x209100b6, u8, + MsgoutNmeaIdGnsUart2, 0x209100b7, u8, + MsgoutNmeaIdGnsUsb, 0x209100b8, u8, + + MsgoutNmeaIdGrsI2c, 0x209100ce, u8, + MsgoutNmeaIdGrsSpi, 0x209100d2, u8, + MsgoutNmeaIdGrsUart1, 0x209100cf, u8, + MsgoutNmeaIdGrsUart2, 0x209100d0, u8, + MsgoutNmeaIdGrsUsb, 0x209100d1, u8, + + MsgoutNmeaIdGsaI2c, 0x209100bf, u8, + MsgoutNmeaIdGsaSpi, 0x209100c3, u8, + MsgoutNmeaIdGsaUart1, 0x209100c0, u8, + MsgoutNmeaIdGsaUart2, 0x209100c1, u8, + MsgoutNmeaIdGsaUsb, 0x209100c2, u8, + + MsgoutNmeaIdGstI2c, 0x209100d3, u8, + MsgoutNmeaIdGstSpi, 0x209100d7, u8, + MsgoutNmeaIdGstUart1, 0x209100d4, u8, + MsgoutNmeaIdGstUart2, 0x209100d5, u8, + MsgoutNmeaIdGstUsb, 0x209100d6, u8, + + MsgoutNmeaIdGsvI2c, 0x209100c4, u8, + MsgoutNmeaIdGsvSpi, 0x209100c8, u8, + MsgoutNmeaIdGsvUart1, 0x209100c5, u8, + MsgoutNmeaIdGsvUart2, 0x209100c6, u8, + MsgoutNmeaIdGsvUsb, 0x209100c7, u8, + + MsgoutNmeaIdRmcI2c, 0x209100ab, u8, + MsgoutNmeaIdRmcSpi, 0x209100af, u8, + MsgoutNmeaIdRmcUart1, 0x209100ac, u8, + MsgoutNmeaIdRmcUart2, 0x209100ad, u8, + MsgoutNmeaIdRmcUsb, 0x209100ae, u8, + + MsgoutNmeaIdVlwI2c, 0x209100e7, u8, + MsgoutNmeaIdVlwSpi, 0x209100eb, u8, + MsgoutNmeaIdVlwUart1, 0x209100e8, u8, + MsgoutNmeaIdVlwUart2, 0x209100e9, u8, + MsgoutNmeaIdVlwUsb, 0x209100ea, u8, + + MsgoutNmeaIdVtgI2c, 0x209100b0, u8, + MsgoutNmeaIdVtgSpi, 0x209100b4, u8, + MsgoutNmeaIdVtgUart1, 0x209100b1, u8, + MsgoutNmeaIdVtgUart2, 0x209100b2, u8, + MsgoutNmeaIdVtgUsb, 0x209100b3, u8, + + MsgoutNmeaIdZdaI2c, 0x209100d8, u8, + MsgoutNmeaIdZdaSpi, 0x209100dc, u8, + MsgoutNmeaIdZdaUart1, 0x209100d9, u8, + MsgoutNmeaIdZdaUart2, 0x209100da, u8, + MsgoutNmeaIdZdaUsb, 0x209100db, u8, + MsgoutUbxRxmRawxI2x, 0x209102a4, u8, MsgoutUbxRxmRawxSpi, 0x209102a8, u8, MsgoutUbxRxmRawxUart1, 0x209102a5, u8, MsgoutUbxRxmRawxUart2, 0x209102a6, u8, MsgoutUbxRxmRawxUsb, 0x209102a7, u8, + MsgoutUbxTimTpI2c, 0x2091017d, u8, + MsgoutUbxTimTpSpi, 0x20910181, u8, + MsgoutUbxTimTpUart1, 0x2091017e, u8, + MsgoutUbxTimTpUart2, 0x2091017f, u8, + MsgoutUbxTimTpUsb, 0x20910180, u8, + // CFG-SIGNAL-* SignalGpsEna, 0x1031001f, bool, SignalGpsL1caEna, 0x10310001, bool, @@ -299,4 +402,37 @@ cfg_val! { SignalGloEna, 0x10310025, bool, SignalGloL1Ena, 0x10310018, bool, SignalGLoL2Ena, 0x1031001a, bool, + + // CFG-TP-* + TpPulseDef, 0x20050023, TpPulse, + TpPulseLengthDef, 0x20050030, TpPulseLength, + TpAntCableDelay, 0x30050001, i16, + TpPeriodTp1, 0x40050002, u32, + TpPeriodLockTp1, 0x40050003, u32, + TpFreqTp1, 0x40050024, u32, + TpFreqLockTp1, 0x40050025, u32, + TpLenTp1, 0x40050004, u32, + TpLenLockTp1, 0x40050005, u32, + TpTp1Ena, 0x10050007, bool, + TpSyncGnssTp1, 0x10050008, bool, + TpUseLockedTp1, 0x10050009, bool, + TpAlignToTowTp1, 0x1005000a, bool, + TpPolTp1, 0x1005000b, bool, + TpTimegridTp1, 0x2005000c, AlignmentToReferenceTime, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum TpPulse { + /// Time pulse period + Period = 0, + /// Time pulse frequency + Freq = 1, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum TpPulseLength { + /// Time pulse ratio + Ratio = 0, + /// Time pulse length + Length = 1, } From 3a5f93c716d2b99e5953535f7bd7e578995da795 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 8 Jun 2022 09:45:33 +0200 Subject: [PATCH 07/17] Make `CfgVal` non-exhaustive. --- ublox/src/ubx_packets/cfg_val.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ublox/src/ubx_packets/cfg_val.rs b/ublox/src/ubx_packets/cfg_val.rs index 9afdcd2..6e74a11 100644 --- a/ublox/src/ubx_packets/cfg_val.rs +++ b/ublox/src/ubx_packets/cfg_val.rs @@ -198,6 +198,7 @@ macro_rules! into_cfg_kv_bytes { macro_rules! cfg_val { ($($cfg_item:ident, $cfg_key_id:expr, $cfg_value_type:ident,)*) => { #[derive(Debug, Clone, Copy)] + #[non_exhaustive] pub enum CfgVal { $( $cfg_item($cfg_value_type), From 286a8abe2215112df3503e5e156367aeb8c761ae Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 8 Jun 2022 09:50:33 +0200 Subject: [PATCH 08/17] Fix unused variable. --- ublox_derive/src/input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ublox_derive/src/input.rs b/ublox_derive/src/input.rs index cf8f761..2ebe09d 100644 --- a/ublox_derive/src/input.rs +++ b/ublox_derive/src/input.rs @@ -577,7 +577,7 @@ fn field_size_bytes(ty: &Type) -> syn::Result> { "Can not interpret array length", )) } - } else if let syn::Type::Reference(ref reference) = ty { + } else if let syn::Type::Reference(_) = ty { Ok(None) } else { let mut valid_type_names = String::with_capacity(200); From fb0ade0852adb5c37c50979d9646fa219dbb1ece Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 8 Jun 2022 10:02:17 +0200 Subject: [PATCH 09/17] Increase MSRV for `const_panic`. --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a2f3e35..c7305cb 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -21,7 +21,7 @@ jobs: - name: Install MSRV uses: actions-rs/toolchain@v1 with: - toolchain: 1.49.0 + toolchain: 1.57.0 override: true components: rustfmt, clippy - name: Build From 5002193f9f2e50782f067a37fc49245c53ec752e Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 8 Jun 2022 11:38:57 +0200 Subject: [PATCH 10/17] Fix unused variable. --- ublox/src/ubx_packets/cfg_val.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ublox/src/ubx_packets/cfg_val.rs b/ublox/src/ubx_packets/cfg_val.rs index 6e74a11..df2eb0a 100644 --- a/ublox/src/ubx_packets/cfg_val.rs +++ b/ublox/src/ubx_packets/cfg_val.rs @@ -209,7 +209,7 @@ macro_rules! cfg_val { pub const fn len(&self) -> usize { match self { $( - Self::$cfg_item(value) => { + Self::$cfg_item(_) => { $cfg_item::SIZE } )* From e9aa87dde75b342f1115cf2c96f9e6f385e4ada0 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 8 Jun 2022 11:53:30 +0200 Subject: [PATCH 11/17] Fix unused fields. --- ublox/src/ubx_packets/packets.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ublox/src/ubx_packets/packets.rs b/ublox/src/ubx_packets/packets.rs index f0a50e2..6109697 100644 --- a/ublox/src/ubx_packets/packets.rs +++ b/ublox/src/ubx_packets/packets.rs @@ -1944,20 +1944,20 @@ pub struct MeasurementIter<'a> { #[derive(Debug, Clone)] pub struct Measurement { - pr_mes: f64, - cp_mes: f64, - do_mes: f32, - gnss_id: u8, - sv_id: u8, - sig_id: u8, - freq_id: u8, - lock_time: u16, - cno: u8, - pr_stdev: u8, - cp_stdev: u8, - do_stdev: u8, - trk_stat: u8, - reserved2: u8, + pub pr_mes: f64, + pub cp_mes: f64, + pub do_mes: f32, + pub gnss_id: u8, + pub sv_id: u8, + pub sig_id: u8, + pub freq_id: u8, + pub lock_time: u16, + pub cno: u8, + pub pr_stdev: u8, + pub cp_stdev: u8, + pub do_stdev: u8, + pub trk_stat: u8, + pub reserved2: u8, } impl Measurement { From 9eb1a4179eb4b1d8846b691e8cd2ff641795fb85 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 8 Jun 2022 12:00:45 +0200 Subject: [PATCH 12/17] Fix tests. --- README.md | 8 ++++---- ublox/src/lib.rs | 8 ++++---- ublox_derive/src/output.rs | 3 ++- ublox_derive/src/tests.rs | 16 +++++++++++++--- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f58f233..00d2b89 100644 --- a/README.md +++ b/README.md @@ -21,15 +21,15 @@ Constructing Packets Constructing packets happens using the `Builder` variant of the packet, for example: ``` -use ublox::{CfgPrtUartBuilder, UartPortId}; +use ublox::{CfgPrtUartBuilder, UartPortId, UartMode, DataBits, Parity, StopBits, InProtoMask, OutProtoMask}; let packet: [u8; 28] = CfgPrtUartBuilder { portid: UartPortId::Uart1, reserved0: 0, tx_ready: 0, - mode: 0x8d0, + mode: UartMode::new(DataBits::Eight, Parity::None, StopBits::One), baud_rate: 9600, - in_proto_mask: 0x07, - out_proto_mask: 0x01, + in_proto_mask: InProtoMask::all(), + out_proto_mask: OutProtoMask::UBLOX, flags: 0, reserved5: 0, }.into_packet_bytes(); diff --git a/ublox/src/lib.rs b/ublox/src/lib.rs index 96a9822..2fc0263 100644 --- a/ublox/src/lib.rs +++ b/ublox/src/lib.rs @@ -9,16 +9,16 @@ //! //! Constructing packets happens using the `Builder` variant of the packet, for example: //! ``` -//! use ublox::{CfgPrtUartBuilder, UartPortId}; +//! use ublox::{CfgPrtUartBuilder, UartPortId, UartMode, DataBits, Parity, StopBits, InProtoMask, OutProtoMask}; //! //! let packet: [u8; 28] = CfgPrtUartBuilder { //! portid: UartPortId::Uart1, //! reserved0: 0, //! tx_ready: 0, -//! mode: 0x8d0, +//! mode: UartMode::new(DataBits::Eight, Parity::None, StopBits::One), //! baud_rate: 9600, -//! in_proto_mask: 0x07, -//! out_proto_mask: 0x01, +//! in_proto_mask: InProtoMask::all(), +//! out_proto_mask: OutProtoMask::UBLOX, //! flags: 0, //! reserved5: 0, //! }.into_packet_bytes(); diff --git a/ublox_derive/src/output.rs b/ublox_derive/src/output.rs index 376a6c1..99affaf 100644 --- a/ublox_derive/src/output.rs +++ b/ublox_derive/src/output.rs @@ -175,6 +175,7 @@ pub fn generate_recv_code_for_packet(pack_descr: &PackDesc) -> TokenStream { #[doc = "Contains a reference to an underlying buffer, contains accessor methods to retrieve data."] pub struct #ref_name<'a>(&'a [u8]); impl<'a> #ref_name<'a> { + #[inline] pub fn as_bytes(&self) -> &[u8] { self.0 } @@ -361,7 +362,7 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { } else { ret.extend(quote! { impl #payload_struct_lifetime #payload_struct #payload_struct_lifetime { - #[inline] + #[inline] pub fn extend_to(self, out: &mut T) where T: core::iter::Extend + diff --git a/ublox_derive/src/tests.rs b/ublox_derive/src/tests.rs index 0250e8c..aee3540 100644 --- a/ublox_derive/src/tests.rs +++ b/ublox_derive/src/tests.rs @@ -51,6 +51,11 @@ fn test_ubx_packet_recv_simple() { #[doc = "Contains a reference to an underlying buffer, contains accessor methods to retrieve data."] pub struct TestRef<'a>(&'a [u8]); impl<'a> TestRef<'a> { + #[inline] + pub fn as_bytes(&self) -> &[u8] { + self.0 + } + #[doc = ""] #[inline] pub fn itow(&self) -> u32 { @@ -192,6 +197,11 @@ fn test_ubx_packet_recv_dyn_len() { #[doc = "Contains a reference to an underlying buffer, contains accessor methods to retrieve data."] pub struct TestRef<'a>(&'a [u8]); impl<'a> TestRef<'a> { + #[inline] + pub fn as_bytes(&self) -> &[u8] { + self.0 + } + #[doc = ""] #[inline] pub fn f1_raw(&self) -> &[u8] { @@ -308,9 +318,9 @@ fn test_ubx_packet_send() { ret[13usize] = bytes[3usize]; let bytes = self.a.to_le_bytes(); ret[14usize] = bytes[0usize]; - let (ck_a, ck_b) = ubx_checksum(&ret[2..17usize - 2]); - ret[17usize - 2] = ck_a; - ret[17usize - 1] = ck_b; + let (ck_a, ck_b) = ubx_checksum(&ret[2..(Self::PACKET_LEN - 2)]); + ret[Self::PACKET_LEN - 2] = ck_a; + ret[Self::PACKET_LEN - 1] = ck_b; ret } } From 96142d841da181304e357981bb400412bef87e3b Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 25 Jul 2022 08:26:01 +0200 Subject: [PATCH 13/17] Add TIM-TM2 commands. --- ublox/src/ubx_packets/cfg_val.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ublox/src/ubx_packets/cfg_val.rs b/ublox/src/ubx_packets/cfg_val.rs index df2eb0a..2e18d16 100644 --- a/ublox/src/ubx_packets/cfg_val.rs +++ b/ublox/src/ubx_packets/cfg_val.rs @@ -387,6 +387,12 @@ cfg_val! { MsgoutUbxTimTpUart2, 0x2091017f, u8, MsgoutUbxTimTpUsb, 0x20910180, u8, + MsgoutUbxTimTm2I2c, 0x20910178, u8, + MsgoutUbxTimTm2Spi, 0x2091017c, u8, + MsgoutUbxTimTm2Uart1, 0x20910179, u8, + MsgoutUbxTimTm2Uart2, 0x2091017a, u8, + MsgoutUbxTimTm2Usb, 0x2091017b, u8, + // CFG-SIGNAL-* SignalGpsEna, 0x1031001f, bool, SignalGpsL1caEna, 0x10310001, bool, From 38b523c5a10583d8cdedbd5b44fcfd02b554f639 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 25 Jul 2022 08:26:16 +0200 Subject: [PATCH 14/17] Add TIM packets. --- ublox/src/ubx_packets/packets.rs | 209 +++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) diff --git a/ublox/src/ubx_packets/packets.rs b/ublox/src/ubx_packets/packets.rs index 6109697..871bd2d 100644 --- a/ublox/src/ubx_packets/packets.rs +++ b/ublox/src/ubx_packets/packets.rs @@ -1899,6 +1899,213 @@ pub enum MsgAckInfoCode { RejectedUnknownType = 6, } +/// Time pulse time data +#[ubx_packet_recv] +#[ubx(class = 0x0d, id = 0x01, fixed_payload_len = 16)] +struct TimTp { + /// Time pulse time of week according to time base + tow_ms: u32, + /// Submillisecond part of towMS (scaling: 2^(-32)) + tow_sub_ms: u32, + /// Quantization error of time pulse + q_err: i32, + /// Time pulse week number according to time base + week: u16, + /// Flags + #[ubx(map_type = TimTpFlags, from = TimTpFlags)] + flags: u8, + /// Time reference information + #[ubx(map_type = TimTpRefInfo, from = TimTpRefInfo)] + ref_info: u8, +} + +#[derive(Debug, Clone)] +pub struct TimTpFlags(u8); + +impl TimTpFlags { + /// Time base + pub fn time_base(&self) -> TimTpTimeBase { + if self.0 & 0b1 == 0 { + TimTpTimeBase::Gnss + } else { + TimTpTimeBase::Utc + } + } + + /// UTC availability + pub fn utc_available(&self) -> bool { + self.0 & 0b10 != 0 + } + + /// (T)RAIM state + /// + /// Returns `None` if unavailale. + pub fn raim_active(&self) -> Option { + match (self.0 >> 2) & 0b11 { + // Inactive. + 0b01 => Some(false), + // Active. + 0b10 => Some(true), + // Unavailable. + _ => None, + } + } + + /// Quantization error validity + pub fn q_err_valid(&self) -> bool { + self.0 & 0b10000 == 0 + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum TimTpTimeBase { + Gnss, + Utc, +} + +#[derive(Debug, Clone)] +pub struct TimTpRefInfo(u8); + +impl TimTpRefInfo { + /// GNSS reference information. Only valid if time base is GNSS. + pub fn time_ref_gnss(&self) -> Option { + Some(match self.0 & 0b1111 { + 0 => TimTpRefInfoTimeRefGnss::Gps, + 1 => TimTpRefInfoTimeRefGnss::Glo, + 2 => TimTpRefInfoTimeRefGnss::Bds, + 3 => TimTpRefInfoTimeRefGnss::Gal, + 4 => TimTpRefInfoTimeRefGnss::NavIc, + _ => return None, + }) + } + + /// UTC standard identifier. Only valid if time base is UTC. + pub fn utc_standard(&self) -> Option { + Some(match self.0 >> 4 { + 1 => TimTpRefInfoUtcStandard::Crl, + 2 => TimTpRefInfoUtcStandard::Nist, + 3 => TimTpRefInfoUtcStandard::Usno, + 4 => TimTpRefInfoUtcStandard::Bipm, + 5 => TimTpRefInfoUtcStandard::Eu, + 6 => TimTpRefInfoUtcStandard::Su, + 7 => TimTpRefInfoUtcStandard::Ntsc, + 8 => TimTpRefInfoUtcStandard::Npli, + _ => return None, + }) + } +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum TimTpRefInfoTimeRefGnss { + Gps, + Glo, + Bds, + Gal, + NavIc, +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum TimTpRefInfoUtcStandard { + Crl, + Nist, + Usno, + Bipm, + Eu, + Su, + Ntsc, + Npli, +} + +/// Time mark data +#[ubx_packet_recv] +#[ubx(class = 0x0d, id = 0x03, fixed_payload_len = 28)] +struct TimTm2 { + /// Channel (i.e. EXTINT) upon which the pulse was measured + ch: u8, + /// Flags + #[ubx(map_type = TimTm2Flags, from = TimTm2Flags)] + flags: u8, + /// Rising edge counter + count: u16, + /// Week number of last rising edge + wn_r: u16, + /// Week number of last falling edge + wn_f: u16, + /// Tow of rising edge + tow_ms_r: u32, + /// Millisecond fraction of tow of rising edge in nanoseconds + tow_sub_ms_r: u32, + /// Tow of falling edge + tow_ms_f: u32, + /// Millisecond fraction of tow of falling edge in nanoseconds + tow_sub_ms_f: u32, + /// Accuracy estimate + acc_est: u32, +} + +#[derive(Debug, Clone)] +pub struct TimTm2Flags(u8); + +impl TimTm2Flags { + pub fn mode(&self) -> TimTm2Mode { + if self.0 & 0b1 == 0 { + TimTm2Mode::Single + } else { + TimTm2Mode::Running + } + } + + pub fn run(&self) -> TimTm2Run { + if self.0 & 0b10 == 0 { + TimTm2Run::Armed + } else { + TimTm2Run::Stopped + } + } + + pub fn new_falling_edge(&self) -> bool { + self.0 & 0b100 != 0 + } + + pub fn new_rising_edge(&self) -> bool { + self.0 & 0b10000000 != 0 + } + + pub fn time_base(&self) -> TimTm2TimeBase { + match self.0 & 0b11000 { + 0 => TimTm2TimeBase::Receiver, + 1 => TimTm2TimeBase::Gnss, + 2 => TimTm2TimeBase::Utc, + _ => unreachable!(), + } + } + + /// UTC availability + pub fn utc_available(&self) -> bool { + self.0 & 0b100000 != 0 + } + + pub fn time_valid(&self) -> bool { + self.0 & 0b1000000 != 0 + } +} + +pub enum TimTm2Mode { + Single, + Running, +} + +pub enum TimTm2Run { + Armed, + Stopped, +} + +pub enum TimTm2TimeBase { + Receiver, + Gnss, + Utc, +} + #[ubx_packet_recv] #[ubx(class = 0x02, id = 0x15, max_payload_len = 8176)] // 16 + 255 * 32 struct RxmRawx { @@ -2178,6 +2385,8 @@ define_recv_packets!( InfTest, InfDebug, RxmRawx, + TimTp, + TimTm2, MonVer, MonHw, RxmRtcm From fa95fd8976127103f5dbfff49887afe7d76e5456 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 10 Sep 2022 07:59:48 +0200 Subject: [PATCH 15/17] Format code. --- ublox/src/ubx_packets/cfg_val.rs | 40 ++--- ublox/src/ubx_packets/packets.rs | 294 +++++++++++++++---------------- 2 files changed, 167 insertions(+), 167 deletions(-) diff --git a/ublox/src/ubx_packets/cfg_val.rs b/ublox/src/ubx_packets/cfg_val.rs index 2e18d16..08296e2 100644 --- a/ublox/src/ubx_packets/cfg_val.rs +++ b/ublox/src/ubx_packets/cfg_val.rs @@ -59,7 +59,7 @@ macro_rules! from_cfg_v_bytes { u16::from_le_bytes([$buf[0], $buf[1]]) }; ($buf:expr, i16) => { - i16::from_le_bytes([$buf[0], $buf[1]]) + i16::from_le_bytes([$buf[0], $buf[1]]) }; ($buf:expr, u32) => { u32::from_le_bytes([$buf[0], $buf[1], $buf[2], $buf[3]]) @@ -102,19 +102,19 @@ macro_rules! from_cfg_v_bytes { } }; ($buf:expr, TpPulse) => { - match $buf[0] { - 0 => TpPulse::Period, - 1 => TpPulse::Freq, - _ => unreachable!(), - } + match $buf[0] { + 0 => TpPulse::Period, + 1 => TpPulse::Freq, + _ => unreachable!(), + } }; ($buf:expr, TpPulseLength) => { - match $buf[0] { - 0 => TpPulseLength::Ratio, - 1 => TpPulseLength::Length, - _ => unreachable!(), - } -}; + match $buf[0] { + 0 => TpPulseLength::Ratio, + 1 => TpPulseLength::Length, + _ => unreachable!(), + } + }; } macro_rules! into_cfg_kv_bytes { @@ -430,16 +430,16 @@ cfg_val! { #[derive(Debug, Clone, Copy, PartialEq)] pub enum TpPulse { - /// Time pulse period - Period = 0, - /// Time pulse frequency - Freq = 1, + /// Time pulse period + Period = 0, + /// Time pulse frequency + Freq = 1, } #[derive(Debug, Clone, Copy, PartialEq)] pub enum TpPulseLength { - /// Time pulse ratio - Ratio = 0, - /// Time pulse length - Length = 1, + /// Time pulse ratio + Ratio = 0, + /// Time pulse length + Length = 1, } diff --git a/ublox/src/ubx_packets/packets.rs b/ublox/src/ubx_packets/packets.rs index 871bd2d..7d2361e 100644 --- a/ublox/src/ubx_packets/packets.rs +++ b/ublox/src/ubx_packets/packets.rs @@ -1903,207 +1903,207 @@ pub enum MsgAckInfoCode { #[ubx_packet_recv] #[ubx(class = 0x0d, id = 0x01, fixed_payload_len = 16)] struct TimTp { - /// Time pulse time of week according to time base - tow_ms: u32, - /// Submillisecond part of towMS (scaling: 2^(-32)) - tow_sub_ms: u32, - /// Quantization error of time pulse - q_err: i32, - /// Time pulse week number according to time base - week: u16, - /// Flags - #[ubx(map_type = TimTpFlags, from = TimTpFlags)] - flags: u8, - /// Time reference information - #[ubx(map_type = TimTpRefInfo, from = TimTpRefInfo)] - ref_info: u8, + /// Time pulse time of week according to time base + tow_ms: u32, + /// Submillisecond part of towMS (scaling: 2^(-32)) + tow_sub_ms: u32, + /// Quantization error of time pulse + q_err: i32, + /// Time pulse week number according to time base + week: u16, + /// Flags + #[ubx(map_type = TimTpFlags, from = TimTpFlags)] + flags: u8, + /// Time reference information + #[ubx(map_type = TimTpRefInfo, from = TimTpRefInfo)] + ref_info: u8, } #[derive(Debug, Clone)] pub struct TimTpFlags(u8); impl TimTpFlags { - /// Time base - pub fn time_base(&self) -> TimTpTimeBase { - if self.0 & 0b1 == 0 { - TimTpTimeBase::Gnss - } else { - TimTpTimeBase::Utc - } - } - - /// UTC availability - pub fn utc_available(&self) -> bool { - self.0 & 0b10 != 0 - } - - /// (T)RAIM state - /// - /// Returns `None` if unavailale. - pub fn raim_active(&self) -> Option { - match (self.0 >> 2) & 0b11 { - // Inactive. - 0b01 => Some(false), - // Active. - 0b10 => Some(true), - // Unavailable. - _ => None, - } - } - - /// Quantization error validity - pub fn q_err_valid(&self) -> bool { - self.0 & 0b10000 == 0 - } + /// Time base + pub fn time_base(&self) -> TimTpTimeBase { + if self.0 & 0b1 == 0 { + TimTpTimeBase::Gnss + } else { + TimTpTimeBase::Utc + } + } + + /// UTC availability + pub fn utc_available(&self) -> bool { + self.0 & 0b10 != 0 + } + + /// (T)RAIM state + /// + /// Returns `None` if unavailale. + pub fn raim_active(&self) -> Option { + match (self.0 >> 2) & 0b11 { + // Inactive. + 0b01 => Some(false), + // Active. + 0b10 => Some(true), + // Unavailable. + _ => None, + } + } + + /// Quantization error validity + pub fn q_err_valid(&self) -> bool { + self.0 & 0b10000 == 0 + } } #[derive(Debug, Clone, Copy, PartialEq)] pub enum TimTpTimeBase { - Gnss, - Utc, + Gnss, + Utc, } #[derive(Debug, Clone)] pub struct TimTpRefInfo(u8); impl TimTpRefInfo { - /// GNSS reference information. Only valid if time base is GNSS. - pub fn time_ref_gnss(&self) -> Option { - Some(match self.0 & 0b1111 { - 0 => TimTpRefInfoTimeRefGnss::Gps, - 1 => TimTpRefInfoTimeRefGnss::Glo, - 2 => TimTpRefInfoTimeRefGnss::Bds, - 3 => TimTpRefInfoTimeRefGnss::Gal, - 4 => TimTpRefInfoTimeRefGnss::NavIc, - _ => return None, - }) - } - - /// UTC standard identifier. Only valid if time base is UTC. - pub fn utc_standard(&self) -> Option { - Some(match self.0 >> 4 { - 1 => TimTpRefInfoUtcStandard::Crl, - 2 => TimTpRefInfoUtcStandard::Nist, - 3 => TimTpRefInfoUtcStandard::Usno, - 4 => TimTpRefInfoUtcStandard::Bipm, - 5 => TimTpRefInfoUtcStandard::Eu, - 6 => TimTpRefInfoUtcStandard::Su, - 7 => TimTpRefInfoUtcStandard::Ntsc, - 8 => TimTpRefInfoUtcStandard::Npli, - _ => return None, - }) - } + /// GNSS reference information. Only valid if time base is GNSS. + pub fn time_ref_gnss(&self) -> Option { + Some(match self.0 & 0b1111 { + 0 => TimTpRefInfoTimeRefGnss::Gps, + 1 => TimTpRefInfoTimeRefGnss::Glo, + 2 => TimTpRefInfoTimeRefGnss::Bds, + 3 => TimTpRefInfoTimeRefGnss::Gal, + 4 => TimTpRefInfoTimeRefGnss::NavIc, + _ => return None, + }) + } + + /// UTC standard identifier. Only valid if time base is UTC. + pub fn utc_standard(&self) -> Option { + Some(match self.0 >> 4 { + 1 => TimTpRefInfoUtcStandard::Crl, + 2 => TimTpRefInfoUtcStandard::Nist, + 3 => TimTpRefInfoUtcStandard::Usno, + 4 => TimTpRefInfoUtcStandard::Bipm, + 5 => TimTpRefInfoUtcStandard::Eu, + 6 => TimTpRefInfoUtcStandard::Su, + 7 => TimTpRefInfoUtcStandard::Ntsc, + 8 => TimTpRefInfoUtcStandard::Npli, + _ => return None, + }) + } } #[derive(Debug, Copy, Clone, PartialEq)] pub enum TimTpRefInfoTimeRefGnss { - Gps, - Glo, - Bds, - Gal, - NavIc, + Gps, + Glo, + Bds, + Gal, + NavIc, } #[derive(Debug, Copy, Clone, PartialEq)] pub enum TimTpRefInfoUtcStandard { - Crl, - Nist, - Usno, - Bipm, - Eu, - Su, - Ntsc, - Npli, + Crl, + Nist, + Usno, + Bipm, + Eu, + Su, + Ntsc, + Npli, } /// Time mark data #[ubx_packet_recv] #[ubx(class = 0x0d, id = 0x03, fixed_payload_len = 28)] struct TimTm2 { - /// Channel (i.e. EXTINT) upon which the pulse was measured - ch: u8, - /// Flags - #[ubx(map_type = TimTm2Flags, from = TimTm2Flags)] - flags: u8, - /// Rising edge counter - count: u16, - /// Week number of last rising edge - wn_r: u16, - /// Week number of last falling edge - wn_f: u16, - /// Tow of rising edge - tow_ms_r: u32, - /// Millisecond fraction of tow of rising edge in nanoseconds - tow_sub_ms_r: u32, - /// Tow of falling edge - tow_ms_f: u32, - /// Millisecond fraction of tow of falling edge in nanoseconds - tow_sub_ms_f: u32, - /// Accuracy estimate - acc_est: u32, + /// Channel (i.e. EXTINT) upon which the pulse was measured + ch: u8, + /// Flags + #[ubx(map_type = TimTm2Flags, from = TimTm2Flags)] + flags: u8, + /// Rising edge counter + count: u16, + /// Week number of last rising edge + wn_r: u16, + /// Week number of last falling edge + wn_f: u16, + /// Tow of rising edge + tow_ms_r: u32, + /// Millisecond fraction of tow of rising edge in nanoseconds + tow_sub_ms_r: u32, + /// Tow of falling edge + tow_ms_f: u32, + /// Millisecond fraction of tow of falling edge in nanoseconds + tow_sub_ms_f: u32, + /// Accuracy estimate + acc_est: u32, } #[derive(Debug, Clone)] pub struct TimTm2Flags(u8); impl TimTm2Flags { - pub fn mode(&self) -> TimTm2Mode { - if self.0 & 0b1 == 0 { - TimTm2Mode::Single - } else { - TimTm2Mode::Running + pub fn mode(&self) -> TimTm2Mode { + if self.0 & 0b1 == 0 { + TimTm2Mode::Single + } else { + TimTm2Mode::Running + } } - } - pub fn run(&self) -> TimTm2Run { - if self.0 & 0b10 == 0 { - TimTm2Run::Armed - } else { - TimTm2Run::Stopped + pub fn run(&self) -> TimTm2Run { + if self.0 & 0b10 == 0 { + TimTm2Run::Armed + } else { + TimTm2Run::Stopped + } } - } - pub fn new_falling_edge(&self) -> bool { - self.0 & 0b100 != 0 - } + pub fn new_falling_edge(&self) -> bool { + self.0 & 0b100 != 0 + } - pub fn new_rising_edge(&self) -> bool { - self.0 & 0b10000000 != 0 - } + pub fn new_rising_edge(&self) -> bool { + self.0 & 0b10000000 != 0 + } - pub fn time_base(&self) -> TimTm2TimeBase { - match self.0 & 0b11000 { - 0 => TimTm2TimeBase::Receiver, - 1 => TimTm2TimeBase::Gnss, - 2 => TimTm2TimeBase::Utc, - _ => unreachable!(), + pub fn time_base(&self) -> TimTm2TimeBase { + match self.0 & 0b11000 { + 0 => TimTm2TimeBase::Receiver, + 1 => TimTm2TimeBase::Gnss, + 2 => TimTm2TimeBase::Utc, + _ => unreachable!(), + } } - } - /// UTC availability - pub fn utc_available(&self) -> bool { - self.0 & 0b100000 != 0 - } + /// UTC availability + pub fn utc_available(&self) -> bool { + self.0 & 0b100000 != 0 + } - pub fn time_valid(&self) -> bool { - self.0 & 0b1000000 != 0 - } + pub fn time_valid(&self) -> bool { + self.0 & 0b1000000 != 0 + } } pub enum TimTm2Mode { - Single, - Running, + Single, + Running, } pub enum TimTm2Run { - Armed, - Stopped, + Armed, + Stopped, } pub enum TimTm2TimeBase { - Receiver, - Gnss, - Utc, + Receiver, + Gnss, + Utc, } #[ubx_packet_recv] From 3c1d10dd1f5d2f2f8517cc4054d360b485ea3c2c Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 10 Sep 2022 08:06:27 +0200 Subject: [PATCH 16/17] Return early if `size_bytes` is 0. --- ublox_derive/src/output.rs | 45 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/ublox_derive/src/output.rs b/ublox_derive/src/output.rs index 99affaf..22fa295 100644 --- a/ublox_derive/src/output.rs +++ b/ublox_derive/src/output.rs @@ -234,35 +234,34 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { #[doc = #field_comment] pub #name: #ty }); + let size_bytes = match f.size_bytes { Some(x) => x.get(), - None => 0, + None => { + // Iterator with `data` field. + extend_fields.push(quote! { + for f in self.#name { + len_bytes += f.extend_to(out); + } + }); + + builder_needs_lifetime = true; + continue; + } }; - if size_bytes == 0 { - // Iterator with `data` field. - extend_fields.push(quote! { - for f in self.#name { - len_bytes += f.extend_to(out); - } + if let Some(into_fn) = f.map.map_type.as_ref().map(|x| &x.into_fn) { + pack_fields.push(quote! { + let bytes = #into_fn(self.#name).to_le_bytes() + }); + } else if !f.is_field_raw_ty_byte_array() { + pack_fields.push(quote! { + let bytes = self.#name.to_le_bytes() }); - - builder_needs_lifetime = true; - continue; } else { - if let Some(into_fn) = f.map.map_type.as_ref().map(|x| &x.into_fn) { - pack_fields.push(quote! { - let bytes = #into_fn(self.#name).to_le_bytes() - }); - } else if !f.is_field_raw_ty_byte_array() { - pack_fields.push(quote! { - let bytes = self.#name.to_le_bytes() - }); - } else { - pack_fields.push(quote! { - let bytes: &[u8] = &self.#name; - }); - } + pack_fields.push(quote! { + let bytes: &[u8] = &self.#name; + }); } write_fields.push(pack_fields.last().unwrap().clone()); From a52005ab34f4286f97ada321d97efeb98b0b9a44 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 10 Sep 2022 08:16:38 +0200 Subject: [PATCH 17/17] Assert iterator field is last field. --- ublox_derive/src/output.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ublox_derive/src/output.rs b/ublox_derive/src/output.rs index 22fa295..e24e6ee 100644 --- a/ublox_derive/src/output.rs +++ b/ublox_derive/src/output.rs @@ -226,7 +226,7 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { let mut write_fields = Vec::with_capacity(pack_descr.fields.len()); let mut extend_fields = Vec::with_capacity(pack_descr.fields.len()); let mut off = 6usize; - for f in &pack_descr.fields { + for (fi, f) in pack_descr.fields.iter().enumerate() { let ty = f.intermediate_type(); let name = f.intermediate_field_name(); let field_comment = &f.comment; @@ -246,7 +246,9 @@ pub fn generate_send_code_for_packet(pack_descr: &PackDesc) -> TokenStream { }); builder_needs_lifetime = true; - continue; + + assert_eq!(fi, pack_descr.fields.len() - 1, "Iterator field must be the last field."); + break; } };