{{self::description_to_docstring(field_set.description)}}
{{ self::maybe_doc_alias(field_set.name, Case::Pascal) }}
#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(transparent)]
pub struct {{field_set.name.to_case(Case::Pascal)}} {
#[doc(hidden)]
/// The internal bits
bits: [u8; {{field_set.size_bytes}}]
}
unsafe impl ::device_driver::Fieldset for {{field_set.name.to_case(Case::Pascal)}} {
const METADATA: ::device_driver::FieldsetMetadata =
::device_driver::FieldsetMetadata::new()
.with_byte_order(::device_driver::ByteOrder::{{field_set.byte_order}});
const ZERO: Self = Self { bits: [0; {{field_set.size_bytes}}] };
}
impl {{field_set.name.to_case(Case::Pascal)}} {
{% for field in field_set.fields %}
{% if matches!(field.access, Access::RW | Access::RO) %}
/// `{{field.address_text()}}` - Read the `{{field.name.to_case(Case::Snake)}}` field.
///
{{ self::description_to_docstring(field.description) }}
{{ self::maybe_doc_alias(field.name, Case::Snake) }}
#[must_use]
pub fn {{field.name.to_case(Case::Snake)}}(
&self,
{% match field.repeat %}
{% when Repeat::None %}
{% when Repeat::Count { .. } %} index: usize
{% when Repeat::Enum { enum_name, .. } %} index: {{enum_name.to_case(Case::Pascal)}}
{% endmatch %}
) ->
{% match field.conversion_method %}
{% when FieldConversionMethod::None %} {{field.base_type}}
{% when FieldConversionMethod::Into(t) | FieldConversionMethod::UnsafeInto(t) %} {{t.to_case(Case::Pascal)}}
{% when FieldConversionMethod::TryInto(t) %} Result<{{t.to_case(Case::Pascal)}}, <{{t.to_case(Case::Pascal)}} as TryFrom<{{field.base_type}}>>::Error>
{% when FieldConversionMethod::Bool %} bool
{% endmatch %}
{
{% match field.repeat %}
{% when Repeat::None %}
let start = {{field.address.start}};
let end = {{field.address.end}};
{% when Repeat::Count { count, stride } %}
assert!(index < {{count}});
let start = {{field.address.start}} + index * {{stride}};
let end = start + {{field.address.len()}};
{% when Repeat::Enum { enum_name, stride, .. } %}
let start = {{field.address.start}} + {{self::get_enum_base_type(driver, &enum_name)}}::from(index) as usize * {{stride}};
let end = start + {{field.address.len()}};
{% endmatch %}
let raw = unsafe {
::device_driver::ops::load::<
{{field.base_type}},
::device_driver::ops::{{field_set.byte_order}},
>(&self.bits, start, end)
};
{% match field.conversion_method %}
{% when FieldConversionMethod::None %} raw
{% when FieldConversionMethod::Into(t) %} raw.into()
{% when FieldConversionMethod::UnsafeInto(t) %} unsafe { raw.try_into().unwrap_unchecked() }
{% when FieldConversionMethod::TryInto(t) %} raw.try_into()
{% when FieldConversionMethod::Bool %} raw > 0
{% endmatch %}
}
{% endif %}
{% endfor %}
{% for field in field_set.fields %}
{% if matches!(field.access, Access::RW | Access::WO) %}
/// `{{field.address_text()}}` - Set the `{{field.name.to_case(Case::Snake)}}` field.
///
{{ self::description_to_docstring(field.description) }}
{{ self::maybe_doc_alias(field.name, Case::Snake) }}
pub fn set_{{field.name.to_case(Case::Snake)}}(
&mut self,
{% match field.repeat %}
{% when Repeat::None %}
{% when Repeat::Count { .. } %} index: usize,
{% when Repeat::Enum { enum_name, .. } %} index: {{enum_name.to_case(Case::Pascal)}},
{% endmatch %}
value: {% match field.conversion_method %}
{% when FieldConversionMethod::None %} {{field.base_type}}
{% when FieldConversionMethod::Into(t) %} {{t.to_case(Case::Pascal)}}
{% when FieldConversionMethod::UnsafeInto(t) %} {{t.to_case(Case::Pascal)}}
{% when FieldConversionMethod::TryInto(t) %} {{t.to_case(Case::Pascal)}}
{% when FieldConversionMethod::Bool %} bool
{% endmatch %}
) {
{% match field.repeat %}
{% when Repeat::None %}
let start = {{field.address.start}};
let end = {{field.address.end}};
{% when Repeat::Count { count, stride } %}
assert!(index < {{count}});
let start = {{field.address.start}} + index * {{stride}};
let end = start + {{field.address.len()}};
{% when Repeat::Enum { enum_name, stride, .. } %}
let start = {{field.address.start}} + {{self::get_enum_base_type(driver, &enum_name)}}::from(index) as usize * {{stride}};
let end = start + {{field.address.len()}};
{% endmatch %}
let raw =
{% match field.conversion_method %}
{% when FieldConversionMethod::None %} value;
{% when FieldConversionMethod::Bool %} value as _;
{% else %} value.into();
{% endmatch %}
unsafe {
::device_driver::ops::store::<
{{field.base_type}},
::device_driver::ops::{{field_set.byte_order}},
>(raw, start, end, &mut self.bits)
};
}
{% endif %}
{% endfor %}
}
impl Default for {{field_set.name.to_case(Case::Pascal)}} {
fn default() -> Self {
<Self as ::device_driver::Fieldset>::ZERO
}
}
impl From<[u8; {{field_set.size_bytes}}]> for {{field_set.name.to_case(Case::Pascal)}} {
fn from(bits: [u8; {{field_set.size_bytes}}]) -> Self {
Self { bits }
}
}
impl From<{{field_set.name.to_case(Case::Pascal)}}> for [u8; {{field_set.size_bytes}}] {
fn from(val: {{field_set.name.to_case(Case::Pascal)}}) -> Self {
val.bits
}
}
impl core::fmt::Debug for {{field_set.name.to_case(Case::Pascal)}} {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
let mut d = f.debug_struct("{{field_set.name.to_case(Case::Pascal)}}");
{% for field in field_set.fields %}
{% if field.access.is_readable() %}
{% match field.repeat %}
{% when Repeat::None %}
d.field("{{field.name.to_case(Case::Snake)}}", &self.{{field.name.to_case(Case::Snake)}}());
{% when Repeat::Count { count, .. } %}
{% for index in 0..*count %}
d.field("{{field.name.to_case(Case::Snake)}}[{{index}}]", &self.{{field.name.to_case(Case::Snake)}}({{index}}));
{% endfor %}
{% when Repeat::Enum { enum_name, enum_variants, .. } %}
{% for variant in enum_variants %}
d.field("{{field.name.to_case(Case::Snake)}}[{{variant.to_case(Case::Pascal)}}]", &self.{{field.name.to_case(Case::Snake)}}({{enum_name.to_case(Case::Pascal)}}::{{variant.to_case(Case::Pascal)}}));
{% endfor %}
{% endmatch %}
{% endif %}
{% endfor %}
d.finish()
}
}
{% if let Some(defmt_feature) = defmt_feature() %}
#[cfg(feature = "{{defmt_feature}}")]
impl defmt::Format for {{field_set.name.to_case(Case::Pascal)}} {
fn format(&self, f: defmt::Formatter) {
defmt::write!(f, "{{field_set.name.to_case(Case::Pascal)}} {% raw %}{{{% endraw %} ");
{% for field in field_set.fields %}
{% if field.access.is_readable() %}
{% match field.repeat %}
{% when Repeat::None %}
defmt::write!(f, "{{self::get_defmt_fmt_string(field)}}", &self.{{field.name.to_case(Case::Snake)}}());
{% when Repeat::Count { count, .. } %}
{% for index in 0..*count %}
defmt::write!(f, "{{self::get_defmt_fmt_string(field)}}[{{index}}]", &self.{{field.name.to_case(Case::Snake)}}({{index}}));
{% endfor %}
{% when Repeat::Enum { enum_name, enum_variants, .. } %}
{% for variant in enum_variants %}
defmt::write!(f, "{{self::get_defmt_fmt_string(field)}}[{{variant.to_case(Case::Pascal)}}]", &self.{{field.name.to_case(Case::Snake)}}({{enum_name.to_case(Case::Pascal)}}::{{variant.to_case(Case::Pascal)}}));
{% endfor %}
{% endmatch %}
{% endif %}
{% endfor %}
defmt::write!(f, "{% raw %}}}{% endraw %}");
}
}
{% endif %}
impl core::ops::BitAnd for {{field_set.name.to_case(Case::Pascal)}} {
type Output = Self;
fn bitand(mut self, rhs: Self) -> Self::Output {
self &= rhs;
self
}
}
impl core::ops::BitAndAssign for {{field_set.name.to_case(Case::Pascal)}} {
fn bitand_assign(&mut self, rhs: Self) {
for (l, r) in self.bits.iter_mut().zip(&rhs.bits) {
*l &= *r;
}
}
}
impl core::ops::BitOr for {{field_set.name.to_case(Case::Pascal)}} {
type Output = Self;
fn bitor(mut self, rhs: Self) -> Self::Output {
self |= rhs;
self
}
}
impl core::ops::BitOrAssign for {{field_set.name.to_case(Case::Pascal)}} {
fn bitor_assign(&mut self, rhs: Self) {
for (l, r) in self.bits.iter_mut().zip(&rhs.bits) {
*l |= *r;
}
}
}
impl core::ops::BitXor for {{field_set.name.to_case(Case::Pascal)}} {
type Output = Self;
fn bitxor(mut self, rhs: Self) -> Self::Output {
self ^= rhs;
self
}
}
impl core::ops::BitXorAssign for {{field_set.name.to_case(Case::Pascal)}} {
fn bitxor_assign(&mut self, rhs: Self) {
for (l, r) in self.bits.iter_mut().zip(&rhs.bits) {
*l ^= *r;
}
}
}
impl core::ops::Not for {{field_set.name.to_case(Case::Pascal)}} {
type Output = Self;
fn not(mut self) -> Self::Output {
for val in self.bits.iter_mut() {
*val = !*val;
}
self
}
}