{% decl block_generics %}
{% if block.root %}
{% let block_generics = "<I>" %}
{% else %}
{% let block_generics = "<'i, I>" %}
{% endif %}
{{ self::description_to_docstring(block.description) }}
{{ self::maybe_doc_alias(block.name, Case::Pascal) }}
#[derive(Debug)]
pub struct {{ block.name.to_case(Case::Pascal) }}{{block_generics}} {
{% if block.root %}
interface: I,
{% else %}
#[doc(hidden)]
interface: &'i mut I,
{% endif %}
#[doc(hidden)]
#[allow(unused)]
base_address: {{device.internal_address_type}},
}
impl{{block_generics}} {{ block.name.to_case(Case::Pascal) }}{{block_generics}} {
{% if block.root %}
/// Create a new instance of the device
pub const fn new(interface: I) -> Self {
Self { interface, base_address: {{ device.address_offset }} }
}
/// Drop the driver instance and reclaim the interface
pub fn free(self) -> I {
self.interface
}
{% else %}
/// Create a new instance of the block based on device interface
#[doc(hidden)]
fn new(interface: &'i mut I, base_address: {{device.internal_address_type}}) -> Self {
Self { interface, base_address: base_address }
}
{% endif %}
{% for method in block.methods %}
{{ self::description_to_docstring(method.description) }}
{{ self.get_block_method_docs(method) }}
{{ self::maybe_doc_alias(method.name, Case::Snake) }}
pub fn {{ method.name.to_case(Case::Snake) }}(
&mut self,
{% if let BlockMethodType::Block { .. } = method.method_type %}
{% match method.repeat %}
{% when Repeat::None %}
{% when Repeat::Count { .. } %} index: usize
{% when Repeat::Enum { enum_name, .. } %} index: {{enum_name.to_case(Case::Pascal)}}
{% endmatch %}
{% endif %}
) ->
{% match method.method_type %}
{% when BlockMethodType::Block { name } %} {{name.to_case(Case::Pascal)}}<'_, I>
{% when BlockMethodType::Register { field_set_name, access, .. } %}
::device_driver::RegisterOperation<
'_,
Self,
{{field_set_name.to_case(Case::Pascal)}},
{{block.register_address_type}},
::device_driver::{{access}},
{% match method.repeat %}
{% when Repeat::None %} ()
{% when Repeat::Count { count, stride } %} ::device_driver::ArrayRepeat<{{count}}, {{stride}}>
{% when Repeat::Enum { enum_name, stride, .. } %} ::device_driver::EnumRepeat<{{enum_name.to_case(Case::Pascal)}}, {{stride}}>
{% endmatch %}
> where I: ::device_driver::RegisterInterfaceBase<AddressType = {{block.register_address_type}}>
{% when BlockMethodType::Command { field_set_name_in, field_set_name_out } %}
::device_driver::CommandOperation<
'_,
Self,
{{block.command_address_type}},
{{self::get_command_fieldset_name(field_set_name_in)}},
{{self::get_command_fieldset_name(field_set_name_out)}},
{% match method.repeat %}
{% when Repeat::None %} ()
{% when Repeat::Count { count, stride } %} ::device_driver::ArrayRepeat<{{count}}, {{stride}}>
{% when Repeat::Enum { enum_name, stride, .. } %} ::device_driver::EnumRepeat<{{enum_name.to_case(Case::Pascal)}}, {{stride}}>
{% endmatch %}
> where I: ::device_driver::CommandInterfaceBase<AddressType = {{block.command_address_type}}>
{% when BlockMethodType::Buffer { access } %}
::device_driver::BufferOperation<
'_,
Self,
{{block.buffer_address_type}},
::device_driver::{{access}}
> where I: ::device_driver::BufferInterfaceBase<AddressType = {{block.buffer_address_type}}>
{% endmatch %}
{
{% if let BlockMethodType::Block { .. } = method.method_type %}
{% match method.repeat %}
{% when Repeat::None %} let address = self.base_address + {{method.address}};
{% when Repeat::Count { count, stride } %}
let address = {
assert!(index < {{count}});
self.base_address + {{method.address}} + index as {{device.internal_address_type}} * {{stride}}
};
{% when Repeat::Enum { enum_name, stride, .. } %}
let address = self.base_address + {{method.address}} + {{self::get_enum_base_type(driver, &enum_name)}}::from(index) as {{device.internal_address_type}} * {{stride}};
{% endmatch %}
{% else %}
let address = self.base_address + {{method.address}};
{% endif %}
{% match method.method_type %}
{% when BlockMethodType::Block { name } %}
{{name.to_case(Case::Pascal)}}::<'_, I>::new(::device_driver::Block::interface(self), address)
{% endwhen %}
{% when BlockMethodType::Register { field_set_name, access, reset_value } %}
::device_driver::RegisterOperation::new(
self,
address as {{block.register_address_type}},
{% if let Some(rv) = reset_value %}
|| {{field_set_name.to_case(Case::Pascal)}}::from([{{rv.value | join(", ")}}]),
{% else %}
{{field_set_name.to_case(Case::Pascal)}}::default,
{% endif %}
)
{% endwhen %}
{% when BlockMethodType::Command { field_set_name_in, field_set_name_out } %}
::device_driver::CommandOperation::new(self, address as {{block.command_address_type}})
{% endwhen %}
{% when BlockMethodType::Buffer { access } %}
::device_driver::BufferOperation::new(self, address as {{block.buffer_address_type}})
{% endwhen %}
{% endmatch %}
}
{% endfor %}
}
impl{{block_generics}} ::device_driver::Block for {{ block.name.to_case(Case::Pascal) }}{{block_generics}} {
type Interface = I;
type RegisterAddressType = {{ block.register_address_type }};
type CommandAddressType = {{ block.command_address_type }};
type BufferAddressType = {{ block.buffer_address_type }};
type RegisterAddressMode = {{self::get_address_mode_const_value(block.register_address_mode)}};
{% if block.root %}
fn interface(&mut self) -> &mut Self::Interface {
&mut self.interface
}
{% else %}
fn interface(&mut self) -> &mut Self::Interface {
self.interface
}
{% endif %}
}